Jump to content

Chris Vossen

Members
  • Posts

    688
  • Joined

  • Last visited

Everything posted by Chris Vossen

  1. Hello Leadwerks Community! In the game industry everyone is always shuffling around between companies as projects reach different stages of development. Since my senior year of college I have been striving to get on board a production team. So, when Telltale offered me a production internship I jumped at the chance. One of my favorite parts of the transition is that Telltale uses Lua as their scripting language so if I ever run into a production problem that involves scripting I could always jump in and investigate their code! I loved my time at Leadwerks from day drinking with Josh while coding to running our GDC booth. It has been truly amazing. I also wanted to say farewell to the Leadwerks community, you guys have been the most intelligent and professional online community I have ever seen and without you guys Leadwerks would not exist. Thank you all for all the content that you've put up. Seeing games created with the engine make it all worth while. Farewell for now (I am still constantly going check the blogs), Chris Vossen P.S. I can't wait to see Leadwerks on Steam and all the future games that are going to come out of LE3!
  2. oops Rastar you are completely correct. When I said: I should have said C++ programming in Leadwerks, ie how to escape (or enhance) component based programming. Kennar- I agree that all the tutorials should be housed in one spot, so you don't have to scrounge around the forums. As for pdf's we'll have to see about that (although I'm pretty sure there are tools or scripts out there to turn webpages into pdf)
  3. I will make sure to cover the generic knowledge as well.
  4. Between the release of LE3 and the GDC, life at Leadwerks has been busy to say the least. Now that things have settled down (a little) it is time for something that I have been looking forward to for a while: Tutorials! At GDC we were constantly talking about the power and flexibility that direct native code programming allows and how users are not locked into only component based programming. But then you look at the example game Darkness Awaits and see only component based programming and just Lua scripts.... It's time to right these wrongs. A comprehensive series of tutorials are underway that will teach how to use the many tools of the engine as well as demonstrate the capabilities of direct native code programming. This series is currently in the design phase and I am working with universities to make sure that the tutorials not only teach the engine but also cover key game development topics. Here are a few high level design points for the tutorials: Teach the engine and its tools C++ programming First Person Shooter As always I'd love to hear suggestions and ideas! I'll keep updates coming as tutorial development ramps up!
  5. Check out GetTexture: http://www.leadwerks.com/werkspace/page/documentation/_/command-reference/material/materialgettexture-r125 then change of the texture.
  6. I'm a little confused as to the exact nature of the prefab factory. Are you trying to input a prefab name and destination and then have a function that when called will load a prefab at that destination?
  7. I'm currently planning out a multiple week "Let's build a FPS" tutorial. It will be a series of tutorials wherein each week I will cover a new subject (movement, lighting, dealing with assets... etc) resulting in the final outcome of fully playable FPS. More to come on this!
  8. I'm just going to quickly post these 2 bits of code: Top Down Camera: Script.target = nil--Entity "Target" Script.distance = 10--float Script.debugphysics = false--bool Script.debugnavigation = false--bool Script.pitch = 20--float Script.height = 10--float function Script:Start() if self.target==nil then return end --debug functions for viewing physics or navigation in game self.entity:SetDebugPhysicsMode(self.debugphysics) self.entity:SetDebugNavigationMode(self.debugnavigation) --Set the camera's rotation self.entity:SetRotation(self.pitch,0,0) end function Script:UpdatePhysics() --Exit the function if the target entity doesn't exist if self.target==nil then return end --Get the target entity's position, in global coordinates local p0 = self.target:GetPosition(true) --Calculate the new camera offset local offset = Vec3(p0.x,p0.y+self.height,p0.z-self.distance) --Add our original offset vector to the target entity position p0 = offset self.entity:SetPosition(p0,true) end Character movements: (on a goblin model) Script.camera = nil --Entity "camera" --Define animation sequences Script.sequence={} Script.sequence.walk=5 Script.sequence.idle=6 function Script:Start() self.currentyrotation = self.entity:GetRotation().y self.modelrotation = -90 App.window:ShowMouse() end function Script:UpdatePhysics() local window = Window:GetCurrent() local move = (window:MouseDown(Key.LButton) and 1 or 0) local playerscreenpos = self.camera:Project(self.entity:GetPosition(true)) local mousescreenpos = window:GetMousePosition() local vectorbetween = mousescreenpos - playerscreenpos self.currentyrotation = Math:ATan2(vectorbetween.y, vectorbetween.x) + self.modelrotation self.entity:SetInput(self.currentyrotation,move,0) if move ~= 0 then self.entity.animationmanager:SetAnimationSequence(self.sequence.walk,0.04,200) else self.entity.animationmanager:SetAnimationSequence(self.sequence.idle,0.05,200) end end To understand the code basically Math::ATan2 finds the angle between the mouse and the player Camera::Project takes the character position in global space and converts it to screen space.
  9. So the proper way to do it is a call to World:Clear(), unfortunately we forgot to tag it for lua (and document it). I'm posting a bug report for this right now and hopefully the lua tag (and documentation) will be available with the next build.
  10. This is a slippery bug (it is really hard to recreate), that we thought we had pinned down. Make sure your current LE3 copy is up to date (Click on the update button on the installer) and we will check it out.
  11. In the editor I'd create a rocket model, set it's physics shape and collision type, attach a particle effect, and then save it as a prefab. Then in code I'd use the prefab load function:Prefab If I can find the time, maybe. What sort of mouse movement are you thinking of?
  12. @ Rick: Yeah I noticed the problem that after posting 2 "tutorials" the first one become hard to find. Right now the things I am posting are super rough so there is no "Official tutorial" section. But I would like an official tutorials section in the future. But currently there is not enough time. @Shadmar Video tutorials always sound like a good idea, but I always find myself having to rewind, or pause the video and you can't copy and paste stuff. I think ideally a combination of a video tutorial and a written tutorial would be awesome. (But the amount of time to produce quality tutorials would skyrocket)
  13. The Time class contains many handy functions. I'd use Time::GetCurrent local nextoccurrence = Time:GetCurrent() + 6000 (6000 milliseconds aka 6 seconds) if Time:GetCurrent() > nextoccurrence then nextoccurrence = Time:GetCurrent() + 6000 Do the function that you want every 6 seconds here end
  14. Weird, I can't seem to recreate this. For me the camera just floats in mid air. If you zip a copy of your project and msg me with it I'll open it and take a look.
  15. Okay I posted some 3rd person movements code : http://www.leadwerks.com/werkspace/files/file/407-3rd-person-controls/ As well as a blog on how to set up a 3rd person scene: http://www.leadwerks.com/werkspace/blog/110/entry-1057-setting-up-a-map-with-3rd-person-controls-and-camera/ And a step by step code walkthrough of the 3rd person camera: http://www.leadwerks.com/werkspace/blog/110/entry-1058-third-person-camera-code-walk-through/
  16. An in-depth look at a basic Third person camera. Script.target = nil--Entity "Target" Script.distance = 5--float Script.debugphysics = false--bool Script.debugnavigation = false--bool Script.pitch = 35--float Script.angle = 180--float Script.pickradius = 0.5--float Script.verticaloffset = 1.8--float Script.smoothness = 30--int function Script:Start() if self.target==nil then return end --debug functions for viewing physics or navigation in game self.entity:SetDebugPhysicsMode(self.debugphysics) self.entity:SetDebugNavigationMode(self.debugnavigation) end function Script:UpdatePhysics() --Exit the function if the target entity doesn't exist if self.target==nil then return end local originalcamerapos = self.entity:GetPosition(true) local targetpos = self.target:GetPosition(true) local newcamerapos = self.target:GetPosition(true) targetpos.y = targetpos.y+self.verticaloffset self.entity:SetPosition(targetpos) self.entity:SetRotation(self.target:GetRotation(true)) self.entity:Turn(self.pitch,self.angle,0) self.entity:Move(0,0,-self.distance) local targetpickmode = self.target:GetPickMode() self.target:SetPickMode(0) --so that the pick doesn't hit the target newcamerapos = self.entity:GetPosition() local pickinfo = PickInfo() if (App.world:Pick(targetpos,self.entity:GetPosition(),pickinfo,self.pickradius,true)) then newcamerapos = pickinfo.position end newcamerapos.x = Math:Curve(originalcamerapos.x,newcamerapos.x,self.smoothness/Time:GetSpeed()) newcamerapos.y = Math:Curve(originalcamerapos.y,newcamerapos.y,self.smoothness/Time:GetSpeed()) newcamerapos.z = Math:Curve(originalcamerapos.z,newcamerapos.z,self.smoothness/Time:GetSpeed()) self.entity:SetPosition(newcamerapos) self.target:SetPickMode(targetpickmode)--return pick mode to original value end At the top of the code I start off by declaring a set of script variables that will be used throughout the code: Script.target = nil--Entity "Target" Script.distance = 5--float Script.debugphysics = false--bool Script.debugnavigation = false--bool Script.pitch = 35--float Script.angle = 180--float Script.pickradius = 0.5--float Script.verticaloffset = 1.8--float Script.smoothness = 30--int Notice that these declarations all have a "--" followed by a type "float, bool, Entity, int" these are extra parameters that will make the variables appear in the engine: target: The target entity that the camera will follow. distance: The default Z distance the camera will follow behind the target. debugphysics & debugnavigation: Handy debug settings. pitch: The pitch angle the camera will be facing. angle: The angle that the character controller is rotated to. pickradius: The width of the raycast that will check if there are objects between the camera and target verticaloffset: The height of the camera offset. smoothness: How smooth the camera will be when moving between positions. function Script:Start() if self.target==nil then return end --debug functions for viewing physics or navigation in game self.entity:SetDebugPhysicsMode(self.debugphysics) self.entity:SetDebugNavigationMode(self.debugnavigation) end The start function is called once when the script is loaded and should be used to initialize variables. Here I check to make sure there is a target and then do 2 function calls to camera debug modes. function Script:UpdatePhysics() --Exit the function if the target entity doesn't exist if self.target==nil then return end local originalcamerapos = self.entity:GetPosition(true) local targetpos = self.target:GetPosition(true) local newcamerapos = self.target:GetPosition(true) targetpos.y = targetpos.y+self.verticaloffset self.entity:SetPosition(targetpos) self.entity:SetRotation(self.target:GetRotation(true)) self.entity:Turn(self.pitch,self.angle,0) self.entity:Move(0,0,-self.distance) local targetpickmode = self.target:GetPickMode() self.target:SetPickMode(0) --so that the pick doesn't hit the target newcamerapos = self.entity:GetPosition() local pickinfo = PickInfo() if (App.world:Pick(targetpos,self.entity:GetPosition(),pickinfo,self.pickradius,true)) then newcamerapos = pickinfo.position end newcamerapos.x = Math:Curve(originalcamerapos.x,newcamerapos.x,self.smoothness/Time:GetSpeed()) newcamerapos.y = Math:Curve(originalcamerapos.y,newcamerapos.y,self.smoothness/Time:GetSpeed()) newcamerapos.z = Math:Curve(originalcamerapos.z,newcamerapos.z,self.smoothness/Time:GetSpeed()) self.entity:SetPosition(newcamerapos) self.target:SetPickMode(targetpickmode)--return pick mode to original value end The update physics section is where the magic happens, this function is called with every physics update. --Exit the function if the target entity doesn't exist if self.target==nil then return end First I check again that a target entity actually exists. I do this just in case the target entity gets deleted at some point during the game, so that you wont be referencing a nil value later on. local originalcamerapos = self.entity:GetPosition(true) local targetpos = self.target:GetPosition(true) local newcamerapos = self.target:GetPosition(true) Three local variables are declared: originalcamerapos: This will hold the original position of the camera and will be used in the smoothing function later on. targetpos: This variable holds the position of the target entity. newcamerapos: This variable will hold position of the next location a camera will be at. targetpos.y = targetpos.y+self.verticaloffset You want the camera to be positioned above the target character so you add the verticaloffset to targetpos.y self.entity:SetPosition(targetpos) self.entity:SetRotation(self.target:GetRotation(true)) self.entity:Turn(self.pitch,self.angle,0) self.entity:Move(0,0,-self.distance) These 4 function calls are awesome and are all that are needed to set the camera to a third person view. 1. You put the camera in the same position of the target. self.entity:SetPosition(targetpos) 2. You rotate the camera to the same rotation as the target self.entity:SetRotation(self.target:GetRotation(true)) 3.Tilt the camera. self.entity:Turn(self.pitch,self.angle,0) 4.Move the camera backwards along its local z axis. self.entity:Move(0,0,-self.distance) Now the camera is in the correct position, in a perfect world this is all that you would need... but sometimes walls or pillars will come in between the camera and the target blocking the cameras view and that is not cool at all. Luckily we can fix that with picking (a raycast)! local targetpickmode = self.target:GetPickMode() self.target:SetPickMode(0) --so that the pick doesn't hit the target newcamerapos = self.entity:GetPosition() if (App.world:Pick(targetpos,self.entity:GetPosition(),pickinfo,self.pickradius,true)) then newcamerapos = pickinfo.position end First off we don't want our raycast to hit the target so we set the target pickmode to 0, but since other functions in the game might want to hit the target entity with a raycast we first need to save the original pickmode and reset it after our ray cast. We also set the newcamerapos to the entities current position, this is for smoothing later. local targetpickmode = self.target:GetPickMode() self.target:SetPickMode(0) --so that the pick doesn't hit the target newcamerapos = self.entity:GetPosition() Now the fun starts. To understand this code you need to understand how the pick function works. Imagine a scene where there is a wall between the player and the camera: If I was playing this game I'd be pissed because I couldn't see my player all I could see is a wall! So we do a raycast from the target to camera and check if anything is in the way: Then we move the camera in front of the first thing the ray hits: Just as in the lovely pictures, you can perform the same thing in code: local pickinfo = PickInfo() if (App.world:Pick(targetpos,self.entity:GetPosition(),pickinfo,self.pickradius,true)) then newcamerapos = pickinfo.position end local pickinfo = PickInfo() A lightweight class that holds the information if a raycast hits an object. App.world:Pick(targetpos,self.entity:GetPosition(),pickinfo,self.pickradius,true) Does the raycast from the target to the camera (self.entity:GetPosition) pickradius is the radius of the ray, and true means return the 1st object hit. if (App.world:Pick(targetpos,self.entity:GetPosition(),pickinfo,self.pickradius,true)) then newcamerapos = pickinfo.position end If an object is hit, then set the camera's new position in front of that object. The final thing we need to do is to smooth the camera movements so that it doesn't jump around and make users sick. newcamerapos.x = Math:Curve(originalcamerapos.x,newcamerapos.x,self.smoothness/Time:GetSpeed()) newcamerapos.y = Math:Curve(originalcamerapos.y,newcamerapos.y,self.smoothness/Time:GetSpeed()) newcamerapos.z = Math:Curve(originalcamerapos.z,newcamerapos.z,self.smoothness/Time:GetSpeed()) self.entity:SetPosition(newcamerapos) self.target:SetPickMode(targetpickmode)--return pick mode to original value end We call Math::Curve which takes two numbers (the new camera position and the original camera position) and will return a division based on the smoothness. Basically it breaks the camera movement into a bunch of little steps instead of a big jump. For example if your camera had an x value of 0 and the next position was supposed to be at 100, if you just set the position to 100 the user would notice a large jump. but Math:Curve(0,100,10) would break the distance into 10 chunks meaning that instead of a 100 the camera would go to 10, on the first update then to 20, then 30.... basically it would be smoother. Finally we set the pickmode back to it's original value in case a different raycast wants to hit the target. And there you have it, a step by step explanation of the 3rd person camera.
  17. A tutorial for creating map with a goblin that has third person controls and a third person camera 1. Create a new project. Inside the LE3 editor open up the leadwerks project manager click File->Project Manager Once open click "new" select "Lua" project, add a title, and click "Ok". Select your newly created project and click "Ok" 2. Create a platform for the goblin to stand on. In a 2d viewport drag-out a box to be used as a platform. 3. Add a material to the platform. In the assest browser open up the material->developer folder and drag and drop bluegrid.mat onto the platform. 4. Add the goblin model from Darkness Awaits to the new project. Using your file browser navigate to the Darkness Awaits goblin model folder (C:\Leadwerks\Projects\DarknessAwaits\Models\Characters) and copy the goblin folder into your new project. 5. Drag and drop the goblin into the map In the asset browser open up models->goblin. Click on the goblin.mdl icon and drag it into the scene. 6. Set the goblins position and rename it In the Scene browser select SKIN_MESH and change its position to 0,0,0 and change the name to Goblin. 7. Setup the goblin's physics properties With the goblin still selected in the scene browser, click on the Physics tab. Change Physics Mode to "Character Controller" Mass to 1.0 Collision Type to "Character" Character Rotation to 180. (The default model facing is towards the positive Z axis, the goblin model was created facing the negative z axis so you have to rotate the character controller to match the model) 8. Add in a camera In the Object browser select Miscellaneous for object and camera for type. Click in a 2d viewport and click Create (or hit enter). 9. Download Scripts Download the 3rdPersonMovements.Lua and 3rdPersonCamera.Lua http://www.leadwerks...-person-camera/ http://www.leadwerks...erson-controls/ Save these files into your projects script folder (or drag and drop into the asset browser) 10. Attach Scripts to goblin. In the Scene browser, right click on the goblin and select "Add Script" Browse to the 3rdPersonMovements.Lua and click okay Once again right click on the goblin, select "Add Script" and in the Scripts/Animations folder select AnimationManager.lua 11. Attach Scripts to camera. In the Scene browser, right click on the camera and select "Add Script" Browse to 3rdPersonCamera.Lua and click okay. 12. Setup the 3rd Person Camera target. In the scene browser, left click on camera then click on the 3rdpersoncamera tab. now drag and drop the goblin into the camera's target field. 13. Click run On the tool bar click on the run icon, or Game->Run, or press F6 on your keyboard. 14. Run around! Using the W and S keys move the goblin forward and backward or rotate with the A and D keys.
  18. Here is the start of a 3rd person camera. I'll write up a blog explaining the code tomorrow: http://www.leadwerks.com/werkspace/files/file/406-3rd-person-camera/ For those who don't want to click download you can copy and paste this: Script.target = nil--Entity "Target" Script.distance = 5--float Script.debugphysics = false--bool Script.debugnavigation = false--bool Script.pitch = 35--float Script.angle = 180--float Script.pickradius = 0.5--float Script.verticaloffset = 1.8--float Script.smoothness = 30--int function Script:Start() if self.target==nil then return end --debug functions for viewing physics or navigation in game self.entity:SetDebugPhysicsMode(self.debugphysics) self.entity:SetDebugNavigationMode(self.debugnavigation) end function Script:UpdatePhysics() --Exit the function if the target entity doesn't exist if self.target==nil then return end local originalcamerapos = self.entity:GetPosition(true) local targetpos = self.target:GetPosition(true) local newcamerapos = self.target:GetPosition(true) targetpos.y = targetpos.y+self.verticaloffset self.entity:SetPosition(targetpos) self.entity:SetRotation(self.target:GetRotation(true)) self.entity:Turn(self.pitch,self.angle,0) self.entity:Move(0,0,-self.distance) local targetpickmode = self.target:GetPickMode() self.target:SetPickMode(0) --so that the pick doesn't hit the target newcamerapos = self.entity:GetPosition() local pickinfo = PickInfo() if (App.world:Pick(targetpos,self.entity:GetPosition(),pickinfo,self.pickradius,true)) then newcamerapos = pickinfo.position end newcamerapos.x = Math:Curve(originalcamerapos.x,newcamerapos.x,self.smoothness/Time:GetSpeed()) newcamerapos.y = Math:Curve(originalcamerapos.y,newcamerapos.y,self.smoothness/Time:GetSpeed()) newcamerapos.z = Math:Curve(originalcamerapos.z,newcamerapos.z,self.smoothness/Time:GetSpeed()) self.entity:SetPosition(newcamerapos) self.target:SetPickMode(targetpickmode)--return pick mode to original value end
  19. This isn't a tutorial but I uploaded a FreeLook (which I basically stole from Josh) camera that uses the WASD keys and mouse movements. http://www.leadwerks.com/werkspace/files/file/405-freelooklua/ While it's not a true FPS camera, you hopefully could augment it to fit your project.
  20. Josh says that buffers similar to LE2 are in the code, but not officially supported at this time.
  21. If I was going to make 1 tutorial, what subject would you want it to be on?
  22. They will only attack players: function EnemyAttackForEachEntityInAABBDoCallback(entity,extra) if extra~=entity then if entity.player~=nil then extra.goblinai:AttackEnemy(entity.player) end end end
×
×
  • Create New...