From 5978f4cd98ec359d78fb6873ea18b5dfaccacd86 Mon Sep 17 00:00:00 2001 From: turanszkij Date: Wed, 30 May 2018 11:45:01 +0100 Subject: [PATCH] updated sample scripts --- Documentation/ScriptingAPI-Documentation.md | 5 +- README.md | 4 ++ scripts/character_controller_tps.lua | 66 +++++++++++++-------- scripts/dungeon_generator.lua | 4 +- 4 files changed, 50 insertions(+), 29 deletions(-) diff --git a/Documentation/ScriptingAPI-Documentation.md b/Documentation/ScriptingAPI-Documentation.md index e0b78e6b0..83b734070 100644 --- a/Documentation/ScriptingAPI-Documentation.md +++ b/Documentation/ScriptingAPI-Documentation.md @@ -71,7 +71,8 @@ This section describes the common tools for scripting which are not necessarily - backlog_post_list(table list) - fixedupdate() - update() -- render() +- render() +- getDeltaTime() - math.lerp(float a,b,t) - math.clamp(float x,min,max) - math.saturate(float x) @@ -284,6 +285,8 @@ A four component floating point vector. Provides efficient calculations with SIM - Add(Vector v1,v2) : Vector result - Subtract(Vector v1,v2) : Vector result - Multiply(Vector v1,v2) : Vector result +- Multiply(Vector v1, float f) : Vector result +- Multiply(float f, Vector v1) : Vector result - Dot(Vector v1,v2) : Vector result - Cross(Vector v1,v2) : Vector result - Lerp(Vector v1,v2, float t) : Vector result diff --git a/README.md b/README.md index c8bf580d8..959a629c2 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,10 @@ To test the engine, this solution contains several projects which you can build - You can run the "Editor" or the "Tests" project to check out features and play around in a 3D environment, load models, scripts, etc. - You can find a "Template_Windows" project which is a minimal set up to get the engine up and running in a clean Windows 10 application. - Be sure to build in "Release" mode for optimal performance. Debugging support will be reduced. +- Be sure to set an appropriate startup project such as the "Editor" or "Tests" for example. +- There are multiple sample models in the "models" folder. You can load any of them inside the Editor. +- There are multiple sample LUA scripts in the "scripts" folder. You can load any of them inside the Editor, but please check how to use them first by reading the first few lines of the scripts. +- Please open an Issue here on GitHub if you encounter any difficulties. The default renderer is DirectX 11. The DirectX 12 renderer is now available (experimental). Vulkan renderer is now available (experimental). You can specify command line arguments for each application to switch between render devices or other settings. Currently the list of options: diff --git a/scripts/character_controller_tps.lua b/scripts/character_controller_tps.lua index d4a498c1e..cfa633ad3 100644 --- a/scripts/character_controller_tps.lua +++ b/scripts/character_controller_tps.lua @@ -1,4 +1,13 @@ -- Lua Third person camera and character controller script +-- To use this, first load a scene so our character can stand on something. Otherwise, it will be undefined behaviour +-- For example, you can load the dungeon generator script first, then this and you will have a scene to try navigate. +-- +-- CONTROLS: +-- WASD: walk +-- SHIFT: speed +-- SPACE: Jump +-- Right Mouse Button: Camera control +-- Mouse: Rotate camera after pressing Right Mouse Button -- Very simple additive gravity for now local gravity = Vector(0,-0.076,0) @@ -6,16 +15,14 @@ local gravity = Vector(0,-0.076,0) -- Character controller class: characterController = { skeleton = Armature(), - head = Transform(), - meshname = "", - target = Transform(), + target = Transform(), -- Camera will look at this location face = Vector(0,0,1), velocity = Vector(), ray = Ray(), o,p,n = Vector(0,0,0), -- collision props with scene (object,position,normal) savedPointerPos = Vector(), moveSpeed = 0.28, - layerMask = 0x2, + layerMask = 0x2, -- The character will be tagged to use this layer, so scene Picking can filter out the character states = { STAND = 0, @@ -25,12 +32,11 @@ characterController = { }, state = STAND, - Load = function(self,fileName,id,objectname,armaturename,headname) + Load = function(self,fileName,id,objectname,armaturename) self.id = id local model = LoadModel(fileName,id) model.SetLayerMask(self.layerMask) self.skeleton = GetArmature(armaturename) - self.head = self.skeleton.GetBone(headname) end, Reset = function(self) @@ -50,7 +56,7 @@ characterController = { self.velocity.SetY(velocityPrev.GetY()) self.ray = Ray(self.skeleton.GetPosition():Add(self.velocity):Add(Vector(0,4)),Vector(0,-1,0)) self.o,self.p,self.n = Pick(self.ray, PICK_OPAQUE, ~self.layerMask) - if(self.o:IsValid()) then + if(self.o.IsValid()) then self.state = self.states.WALK else self.state = self.states.STAND @@ -61,13 +67,15 @@ characterController = { local ray2 = Ray(self.skeleton.GetPosition():Add(self.velocity:Normalize():Multiply(1.2)):Add(Vector(0,4)),self.velocity) local o2,p2,n2 = Pick(ray2, PICK_OPAQUE, ~self.layerMask) local dist = vector.Subtract(self.skeleton.GetPosition():Add(Vector(0,4)),p2):Length() - if(o2:IsValid() and dist < 2.8) then + if(o2.IsValid() and dist < 2.8) then -- run along wall instead of going through it - local undesiredMotion = n2:Multiply(vector.Dot(self.velocity.Normalize(), n2.Normalize())) - local desiredMotion = vector.Subtract(self.velocity, undesiredMotion) - self.velocity = desiredMotion - + local velocityLen = self.velocity.Length() + local velocityNormalized = self.velocity.Normalize() + local undesiredMotion = n2:Multiply(vector.Dot(velocityNormalized, n2)) + local desiredMotion = vector.Subtract(velocityNormalized, undesiredMotion) + self.velocity = vector.Multiply(desiredMotion, velocityLen) end + end, Turn = function(self,f) self.skeleton.Rotate(Vector(0,f)) @@ -157,17 +165,17 @@ characterController = { end local w,wp,wn = Pick(self.ray,PICK_WATER) - if(w:IsValid() and self.velocity.Length()>0) then + if(w.IsValid() and self.velocity.Length()>0) then PutWaterRipple("../Editor/images/ripple.png",wp) end self.velocity = vector.Add(self.velocity, gravity) - self.skeleton.Translate(self.velocity) + self.skeleton.Translate(vector.Multiply(getDeltaTime() * 60, self.velocity)) self.ray = Ray(self.skeleton.GetPosition():Add(Vector(0,4)),Vector(0,-1,0)) local pPrev = self.p self.o,self.p,self.n = Pick(self.ray, PICK_OPAQUE, ~self.layerMask) - if(not self.o:IsValid()) then + if(not self.o.IsValid()) then self.p=pPrev end if(self.skeleton.GetPosition().GetY() < self.p.GetY() and self.velocity.GetY()<=0) then @@ -201,23 +209,29 @@ tpCamera = { end, Update = function(self) - --camera collision if(self.targetPlayer ~= nil) then local camRestDistance = 12.0 local camTargetDiff = vector.Subtract(self.targetPlayer.target.GetPosition(), self.camera.GetPosition()) - local camTargetDistance = camTargetDiff:Length() + local camTargetDistance = camTargetDiff.Length() + if(camTargetDistance < camRestDistance) then - self.camera.Translate( Vector(0,0,-0.14) ) + -- Camera is closer to target than rest distance, push it back some amount... + self.camera.Translate(vector.Multiply(getDeltaTime() * 60, Vector(0,0,-0.14))) end - local camRay = Ray(self.camera.GetPosition(),camTargetDiff:Normalize()) + + -- Cast a ray from the camera eye and check if it hits something other than the player... + local camRay = Ray(self.camera.GetPosition(),camTargetDiff.Normalize()) local camCollObj,camCollPos,camCollNor = Pick(camRay, PICK_OPAQUE, ~self.targetPlayer.layerMask) - if(camCollObj:IsValid()) then + if(camCollObj.IsValid()) then + -- It hit something, see if it is between the player and camera: local camCollDiff = vector.Subtract(camCollPos, self.camera.GetPosition()) - local camCollDistance = camCollDiff:Length() + local camCollDistance = camCollDiff.Length() if(camCollDistance < camTargetDistance) then + -- If there was something between player and camera, clamp camera position inside: self.camera.Translate(Vector(0,0,camCollDistance)) end end + end end, } @@ -231,6 +245,8 @@ local camera = tpCamera -- Main loop: runProcess(function() + -- We will override the render component so we can invoke the script from Editor and controls won't collide with editor scripts + -- TODO: for example ESC key could bring us back to editor component and destroy this? local component = TiledForwardRenderableComponent() component.SetSSREnabled(false) component.SetSSAOEnabled(false) @@ -239,7 +255,7 @@ runProcess(function() --ClearWorld() --LoadModel("../models/Misc/scene.wimf") - player:Load("../models/girl/girl.wimf","player","omino_common","Armature_common","testa") + player:Load("../models/girl/girl.wimf","player","omino_common","Armature_common") player:Reset() --player:Reposition(Vector(0,4,-20)) camera:Reset() @@ -249,11 +265,11 @@ runProcess(function() player:Input() - camera:Update() - player:Update() - -- Wait for Engine + camera:Update() + + -- Wait for Engine update tick update() end diff --git a/scripts/dungeon_generator.lua b/scripts/dungeon_generator.lua index 04b130023..bb1cd8a00 100644 --- a/scripts/dungeon_generator.lua +++ b/scripts/dungeon_generator.lua @@ -1,7 +1,5 @@ - - - -- Simplistic random dungeon generator lua script +-- You can call this from Editor for example, and it will load a complete dungeon from set pieces local modelpath = "../models/"