Jump to content

And, Hello

Paul Thomas


There are several here who already know me, but for those who don't, my name is Paul Thomas. I've been programming for a long time now; I started when I was 16 (I'm now 30) with HTML, CSS, Javascript, and CGI/Perl. Hell back then there wasn't a lot of people who even used the internet at home, lol. At least in my area, I'm sure others, especially in California, were a lot further ahead at that time in terms of technology and the interest in the technology.


Through the years I've learned multiple languages from strictly web-based to software based. My interest in computers when I was 16 was to make a game, but at the time I thought it would have been much easier to prototype the whole idea in a web-based browser game. I had completed the browser game, which was the original "Eternal Crisis," and worked nicely. My plan was to update the entire web-based system, polish everything, and officially advertise (I had invited friends to play the game). That's when I learned about a "fried hard drive" and eventually learned about "backup" and how to install a hard drive.


Those whom already know me, know what Eternal Crisis is, and my Blogger shows some of the history on that project. I had taken that project, along with another, over to Unreal Engine 3 because it best suit the project. Along the years of learning that engine I was using LE for prototyping ideas and so forth.


While I'm not working on my own engine (temporarily titled "3D Dice"), FPS/RPG framework for UE3, or R.A.T.S., I work on my framework for Leadwerks Engine 2.5. I've never shared this framework before, in fact it always felt like I had to pull it out of a shallow grave each time I added to the framework design and programming. I'm a notebook junkie, I plan out mechanics, structures, and so forth on paper, before going over to digital. Old habbits that die hard I guess.


Now I felt like sharing the progress, which isn't a lot, but it's a great start to me. It's a great start to me because it actually runs, lol. The state of the framework isn't even close to the final planned and written design, but progress is progress. Always move forward until it's finished, even if you can only pick that project up once every two weeks (by then I/you should probably take a look at your workload and fix it instead of attempting such project schedules; however this isn't vital to me and rates low on my importance scale), if it's updated then progress is moving forward. This is also harder to work with if you don't plan your software before actually programming (unless it's routine for you with available libraries for shortcuts in development).


As most programmers should know, the programmers "update" isn't as glamorous as an artists "update" as it's not about visual stimulation but overall program/software flow. In the case of my LE framework (obviously untitled) it's all about providing mechanics and how that is achieved is important especially in the case of LUA access and how everything works together; from configuration/data management, to input binding, and all the way down to AI.


Until occupied again by my other tasks I will eventually share the entire framework structure and I will always be showing examples of syntax; cause that's what programmers do. Just to clear the obvious questions that may come from the community:


Q) Do I plan to give away code, the framework, and be an open source kind of person?

A) No, not really. First of all, you would have to wait, to anyone else at the moment the framework is as useful is a partially finished library. How long you would have to wait would depend on how much time I can spend on the framework and in all honestly it's not much at all (read above, and actually read).


Q) Do I plan to sell or lease the framework?

A) No, don't think so. I even think that's against Leadwerks terms since it could be deemed an "FPS Creator," which is definitely in the terms.


Q) Is my framework really that great?

A) Nah, I mostly ramble, and I'm actually writing this to share with long time friends here at Leadwerks. Some won't even visit anywhere else to communicate because they are so used to using Leadwerks for that; it is indeed where we all met.


Q) Who are my friends?

A) I have none, it was a lie.




Now, about this framework. This "framework" isn't the same, exactly, as the framework that comes with LE. The framework that comes with LE handles some dirty work for you when it comes to creating the worlds, cameras for those worlds, shader effects, and helper functions. The framework I'm designing is technically similar to a game engine. I personally consider Leadwerks Engine as a rendering API with physics and this framework uses that rendering API and provides mechanics. The mechanics the framework provides is what makes up the detail of the framework.








The above are considered "managers" in that they only handle what they should be managing. The "INI" only works with INI files, such as a configuration manager. The "SQL" only works with SQLite3, providing helper functions for easier SQL management, and so forth. There are more planned managers than the above, but these are what are completed in terms of programming. The only real interesting portion to discuss about the framework is within the "Game" manager itself.


The game manager provides two special classes/managers; "Object" and "Actor." Actor inherits everything about an Object. What defines an Object is a game entity that is never interacted with by the player. Objects are useful as it can be used for multiple purposes without consuming a lot of resources for each "component" or "plugin" I'd like to add onto the framework. For example, a Timer would be an Object. You don't interact with a Timer in a game, but there is a timer running in the background.



class ETimer : public EObject
   virtual ~ETimer(void);

   void Initialize(void);
   void SetTimer(float StartTime);
   void StopTimer();


While working with the framework you would do something similar to:

// EGame::EObject
// EGame::Objects
EObject Objects;
// ..
ETimer Timer;
Objects.Add("Timer", Timer);
// ..

ETimer Timer = Objects.Get("Timer");
// ..
// inherited by EObject


An Actor inherits everything that defines an Object. The difference between the two is that an Actor is something that a player could see, hear, interact with, or can move, rotate, and so forth. If you can see how this is all going, everything starts extending the Actor, such as the character, weapon, or items. Here are some examples of working with Actors in the framework:


// EGame::Actors
Actors.Add("oilbarrel", "oilbarrel.gmf");
// ..
Actors.Rotate("oilbarrel", vec3(10.0f, 0.0f, 10.0f));
// ..
Actors.Translate("oilbarrel", vec3(10.0f, 0.0f, 0.0f));
// ..
EActor barrel = Actors.Get("oilbarrel");
// rotate with interpolation
barrel.Rotate(vec3(1.0f), 0.1f);
barrel.Translate(vec3(0.0f, 1.0f, 0.0f), 0.1f);
// ..
EActor Barrel;
// new name
Barrel.Name = "barrel01";
// new mesh
Actors.Edit("oilbarrel", Barrel);


A quick overview of an Actor:



Each Actor can also have children which are also Actors. This provides another version of parent/child relationships but also provides additional benefits which will be discussed in later blogs. The ID and Name variables are provided by Object and the Object provides more variables, but is listed for importance.


When creating an Actor it is automatically tagged for unique identification. In the above example "oilbarrel" is actually stored as "oilbarrel_0" and simply incremented for each Actor that is created. This is identified by the Actors "Tag". The "Name" variable is a forced name, therefore searching for an Actor by the name, with more than one Actor having the same name, the first result is returned.


Actors will be automatically created properly for each entity in a scene. The framework will be using a custom scene manager and handles initial Actor creation. Programmers/Scripters can then add to the Actors list with C++ or LUA like the above examples.


class MyGame : public EGame
   void Load(void);
   void Update(float DeltaTime);
   // ..
   void MyGame::Load(void)
  Actors.Add("custom_actor", "mymesh.gmf", "force_tag_name");

  EActor actor = Actors.Get("custom_actor");
  EActor actorCopy = Actors.GetTag("force_tag_name");


   void MyGame::Update(float DeltaTime)
  EActor actor = Actors.Get("custom_actor");
  // interp move with speed and threshold option
  actor.Move(vec3(10.0f), 1.0f, 1.0f, 0.35f);


In upcoming blogs, when I do get the time, I'll post up some videos. Those selected for the invite only alpha testing will get their information on how to use the framework. Friends of mine that didn't get an invite and are interested in alpha testing please private message me; I most likely didn't send you the information because I figured you were busy with your own project(s).


Well, out of time. Thanks for reading.


Recommended Comments

Sorry ... but who are you?



Paul's been around a long time, he just has a fancy new avatar.

Awesome, it's now fancy. The last time I made a new avatar you said it was emo. I guess this is an improvement. Granted, I stole the overall style from Assassin's Creed. I can't help it, fantastic storyline, awesome era, great art, beautiful mechanics and AI.

Share this comment

Link to comment

Blog Update:

I've been spending time organizing the classes, preparing to share with LUA, and DLL. Figured now while it's early. It may be too early to provide much to LUA or DLL. In any case, soon it's time to move on to actual actors (camera, terrain, volumes/triggers, etc.), after I finish with meshes.

Share this comment

Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Add a comment...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Blog Entries

    • By Josh in Josh's Dev Blog 5
      I did a little experiment with FPS Creator Pack #75 by upsampling the images with Gigapixel, which uses deep learning to upsample images and infer details that don't appear in the original pixels. The AI neural network does a pretty impressive job, generating results that are look better than a simple sharpen filter: I doubled the size of the textures to 1024x1024. Then I generated normal maps from the high-res images using AMD's TGA to DOT3 tool, and saved the normal maps with BC5 DDS compression. The diffuse textures were saved with BC7 DDS compression. The images below are using a 4x magnification to demonstrate the difference.

      As you can see, the image that is upsampled with deep learning looks normal and the resized image looks like there is butter on the lens! It's hard to believe the above images came from a 256x128 section of an image.
      The workflow was pretty tedious, as I had to convert images to TGA, then to uncompressed or BC5 DDS, and then to BC7 in Visual Studio. Each BC7 texture took maybe 5-10 minutes to compress! So while this set represents the optimum quality for 2019 game tech, and the format for assets we want to use in LE5, the workflow has a lot of room for improvement.
      You can download the full package here:
    • By Josh in Josh's Dev Blog 0
      A new beta is available with the following changes:
      Script prefixes are now changed to lowercase entity:Update(), entity:Start(), etc., as well as widget:Draw(), etc. This is because Entity() and Widget() are going to be functions to cast an object to that type. Sprites are now created on a sprite layer object. A sprite layer is created in a world and added to a camera. This allows control over what camera sees what set of sprites. See the examples for details. GUI system is partially working. Resizing the window won't reposition items correctly. Only four widget types are supported, panel, button, hyperlink, and label. Example in the FPSGame demo. The game menu system is packed into an entity script and works really nicely. Widget scripts are a little harder to develop now since they use a system of persistent objects, but performance is very much better than LE4. An interesting detail is that you get free interpolation of position and color at a rate of 60 hz. A lot of work was done to improve the Lua binding system. See details here. Error reporting and handling is much improved. No work was done on sound. No work has been done to the multicam demo, which some people had trouble with. Actors crashing / Lua stack error bug fixed. Changed .bat files to use release version of EXE instead of debug. New commands EmitEvent() and GetEvent(). If the returned event type is EVENT_NONE, there is no event. EVENT_QUIT can be emitted anywhere in the program to signal the main loop to exit. Typical usage is like this: while window:Closed() == false do while true do local event = GetEvent() if event.id == EVENT_QUIT then return end if event.id == EVENT_NONE then break end if event.id == EVENT_WINDOW_CLOSE and Window(event.source) == window then return end--you don't need this when Window:Closed() is being checked for already end world:Update() world:Render(framebuffer) end  
    • By Josh in Josh's Dev Blog 2
      DPI scaling and the 2D drawing and GUI system were an issue I was a bit concerned about, but I think I have it worked out. This all goes back to the multi-monitor support that I designed back in September. Part of that system allows you to retrieve the DPI scale for each display. This gives you another piece of information in addition to the raw screen resolution. The display scale gives you a percentage value the user expects to see vector graphics at, with 100% being what you would expect with a regular HD monitor. If we scale our GUI elements and font sizes by the display scale we can adjust for screens with any pixel density.
      This shot shows 1920x1080 fullscreen with DPI scaling set to 100%:

      Here we see the same resolution, with scaling set to 125%:

      And this is with scaling set to 150%:

      The effect of this is that if the player is using a 4K, 8K, or any other type of monitor, your game can display finely detailed text at the correct size the user expects to see. It also means that user interfaces can be rendered at any resolution for VR.
      Rather than trying to automatically scale GUI elements I am giving you full control over the raw pixels. That means you have to decide how your widgets will be scaled yourself, and program it into the game interface, but there is nothing hidden from the developer. Here is my code I am working with now to create a simple game menu. Also notice there is no CreatePanel(), CreateButton(), etc. anymore, there is just one widget you create and set the script for. I might add an option for C++ actors as well, but since these are operating on the main logic thread there's not really a downside to running the code in Lua.
      local window = ActiveWindow() if window == nullptr then return end local framebuffer = window:GetFramebuffer() if framebuffer == nil then return end self.gui = CreateGUI(self.guispritelayer) --Main background panel self.mainpanel = CreateWidget(self.gui,"",0,0,framebuffer.size.x,framebuffer.size.y) self.mainpanel:SetScript("Scripts/GUI/Panel.lua", true) local scale = window.display.scale.y local w = 120 local h = 24 local sep = 36 local x = framebuffer.size.x / 6 local y = framebuffer.size.y / 2 - sep * 3 self.resumebutton = CreateWidget(self.mainpanel,"RESUME GAME",x,y,w,h) self.resumebutton:SetScript("Scripts/GUI/Hyperlink.lua", true) self.resumebutton:SetFontSize(14 * window.display.scale.y) y=y+sep*2 self.label2 = CreateWidget(self.mainpanel,"OPTIONS",x,y,w,h) self.label2:SetScript("Scripts/GUI/Hyperlink.lua", true) self.label2:SetFontSize(14 * window.display.scale.y) y=y+sep*2 self.quitbutton = CreateWidget(self.mainpanel,"QUIT", x,y, w,h) self.quitbutton:SetScript("Scripts/GUI/Hyperlink.lua", true) self.quitbutton:SetFontSize(14 * window.display.scale.y) w = 400 * scale h = 550 * scale self.optionspanel = CreateWidget(self.mainpanel,"QUIT", (framebuffer.size.x- w) * 0.5, (framebuffer.size.y - h) * 0.5, w, h) self.optionspanel:SetScript("Scripts/GUI/Panel.lua", true) self.optionspanel.color = Vec4(0.2,0.2,0.2,1) self.optionspanel.border = true self.optionspanel.radius = 8 * scale self.optionspanel.hidden = true  
  • Create New...