Jump to content

CrazyM

Members
  • Posts

    86
  • Joined

  • Last visited

Posts posted by CrazyM

  1. Unfortunately, there is no shortage of unappreciative jerks who think tutorial means "Make my game for me". I have really enjoyed your Project Saturn series. Being new to Leadwerks myself, it's been a great series to help me apply my existing knowledge to the Leadwerks workflow, I'd love to see the series continue.

     

    I would also enjoy learning how to use C++ and Lua together.

    • Upvote 1
  2. I tested this in App.lua, but it should work the same in the App.cpp. it does work.

     

    Create a variable to store the window size

    prevScreenSize = Vec2(0,0)
    

    Get the initial window size in start

    self.prevScreenSize = Vec2(Math:Round(self.window:GetWidth()), Math:Round(self.window:GetHeight()))
    

    Check for change, update the variable when change is detected, and call a function

    if self.prevScreenSize.x ~= Math:Round(self.window:GetWidth()) or self.prevScreenSize.y ~= Math:Round(self.window:GetHeight()) then
       self.prevScreenSize = Vec2(Math:Round(self.window:GetWidth()), Math:Round(self.window:GetHeight()))
       self:ScreenSizeChanged()
    end
    
    function App:ScreenSizeChanged()
       System:Print("ScreenSizeChanged: " .. self.prevScreenSize:ToString())
    end
    

  3. If there isn't a built in function, maybe store the window size in a variable in start, then compare that variable with the current window size and when it's different, update the variable with the current size and call a separate function. If getting the current window size is expensive, you could limit a check to every n iterations of the the loop.

     

    Possibly use System::AddHook?

     

    I'm not new to programming, but I am new to Leadwerks, so this may be a terrible idea. :)

  4. In the example output above, the pick was from the -X side, it should have returned (-1,0,0). My test is using a grid aligned cube created in blender, it has a (0,0,0) rotation in the Leadwerks map. The problem does not exist when using a CSG, I am only able to create the problem with the Blender cube import. Interestingly, good values are returned from most of the face surface area from any face, but each face has a seemingly random spot that returns bad values. I have tried a default blender cube, which is off grid by default, with a center origin, a grid aligned blender cube with a center origin, and a grid aligned blender cube with a corner origin, they all produce the same result. I have no idea how a six sided cube can return different normal values from different areas of the same face.

  5. Okay, I made a much simpler script to try to eliminate any other potential causes. It's still not returning clean -1, 0, 1 values, but rather fractions.

     

    Script.player = nil --entity "Player"
    Script.reticle = "" --path "Reticle" "Tex file (*.tex):tex;"
    window = Window:GetCurrent()
    world = World:GetCurrent()
    context = Context:GetCurrent()
    pickradius = 0.1
    pickinfo = nil
    mousePos = nil
    reticleOptic = nil
    function Script:Start()
       pickinfo = PickInfo()
       reticleOptic = Texture:Load(self.reticle)
    end
    function Script:UpdateWorld()
       mousePos = window:GetMousePosition()
       if (self.player.script.camera:Pick(mousePos.x, mousePos.y, pickinfo, pickradius, true)) then
        if pickinfo ~= nil then
    	    if pickinfo.entity:GetKeyValue("name") == "Block" then
    		    --System:Print("Entity: " .. pickinfo.entity:GetPosition():ToString())
    		    --System:Print("Position: " .. pickinfo.position:ToString())
    		    System:Print("Normal: " .. pickinfo.normal:ToString())
    	    end
        end
       end
    end
    function Script:PostRender(context)
       if reticleOptic ~= nil then
        context:SetColor(1,1,1,1)
        context:SetBlendMode(Blend.Alpha)	   
        context:DrawImage(reticleOptic, context:GetWidth()/2-32, context:GetHeight()/2-32, 64, 64)
        context:SetBlendMode(Blend.Solid)
       end   
    end
    

     

    Normal: -0.968764, -0.175351, 0.175352

  6. This is what I'm getting when camera picking the X face of a cube placed on the ground.

     

    if (self.player.script.camera:Pick(mousePos.x, mousePos.y, pickinfo, pickradius, true)) then
       System:Print("Entity: " .. pickinfo.entity:GetPosition():ToString())
       System:Print("Position: " .. pickinfo.position:ToString())
       System:Print("Normal: " .. pickinfo.normal:ToString())
    end
    

     

     

    Entity: -3.000000, 1.000000, 0.000000

    Position: -2.555588, 1.315765, -0.250583

    Normal: 0.740685, 0.526274, -0.417638

  7. Your right, they are correct, it looks like the pickinfo.normal is describing the exact hit position, which is great for adding an impact particle effect at the location a hit occurs, though I wish pickinfo also had a separate return value that simply described the side of the hit. Good for geometric shape placement ;)

     

    pickinfo.entity:GetPosition() + pickinfo.normal = exact hit position
    

  8. Forgive me if this is a silly question, but my previous experience with collision normals is as follows:

     

    collision on X should return Vec3(1,0,0)

    collision on -X should return Vec3(-1,0,0)

    collision on Y should return Vec3(0,1,0)

    collision on -Y should return Vec3(0,-1,0)

    collision on Z should return Vec3(0,0,1)

    collision on -Z should return Vec3(0,0,-1)

     

    Leadwerks pickinfo.normal returns a fraction depending on where on a face the collision occurs. Is pickinfo.face the "normal" function I'm used to, and maybe pickinfo.normal is describing the hit point?

     

    If this is the case, how do you use pickinfo.face, I couldn't find much documentation on it?

     

    Thanks!

  9. I finally got everything working to some degree. It could use some more refinement, but this was just an API familiarization exercise for me.

     

    Thanks everyone for you input and assistance.

     

    Just in case anyone is interested in the basis of a Minecraft style block pick/placement script, here it is.

     

    1. Create a one unit (meter?) cube in your favorite 3D app.

    2. Import and save as a prefab.

    3. Create a pivot, and attached this script to it, then parent the pivot to your FPSPlayer.

    4. Link in the player, prefab, a pickup sound, a placement sound, and a texture reticle.

     

    Left Ctrl = toggles in and out of block building mode

    Right mouse click = places a block

    Left mouse click = removes a block

     

    Cheers!

     

    EDIT:

    Updated to fix some issues

     

    Script.player = nil --entity "Player"
    Script.blockPrefab = "" --path "Prefab" "Prefab (*.pfb):pfb"
    Script.pickSound = "" --path "Pick Sound" "Sound File (*.wav):wav;Ogg Vorbis (*.ogg):ogg"
    Script.placeSound = "" --path "Place Sound" "Sound File (*.wav):wav;Ogg Vorbis (*.ogg):ogg"
    Script.reticle = "" --path "Reticle" "Tex file (*.tex):tex;"
    
    window = Window:GetCurrent()
    world = World:GetCurrent()
    context = Context:GetCurrent()
    pickradius = 0.1
    block = nil
    blockMode = false
    pickinfo = nil
    mousePos = nil
    pickSnd = nil
    placeSnd = nil
    reticleOptic = nil
    
    
    function Script:Start()
       pickinfo = PickInfo()
       pickinfoTest = PickInfo()
       pickSnd = Sound:Load(self.pickSound)
       placeSnd = Sound:Load(self.placeSound)
       reticleOptic = Texture:Load(self.reticle)
    end
    
    
    function Script:UpdateWorld()
       mousePos = window:GetMousePosition()
    
       -- Toggle blockMode
       if window:KeyHit(Key.ControlKey) then
           if blockMode == false then
               blockMode = true
           else
               blockMode = false
           end
       end
    
       -- blockMode
       if blockMode == true then
           -- Load a new block
           if block == nil then            
               block = Prefab:Load(self.blockPrefab)    
               block:SetPickMode(0) -- ignore        
               block:SetCollisionType(4)                
               block:SetKeyValue("name","Block")        
           end
    
           -- Position the block grid aligned and normal offset
           if block ~= nil then
               if (self.player.script.camera:Pick(mousePos.x, mousePos.y, pickinfo, pickradius, true)) then
                   local blockPos = Vec3(Math:Round(pickinfo.position.x), 
                       Math:Round(pickinfo.position.y), 
                       Math:Round(pickinfo.position.z))
    
                   block:SetPosition(blockPos, true)            
               end
           end
    
           -- Place the block
           if window:MouseHit(2) then -- right mouse button
               if placeSnd ~= nil then
                   placeSnd:Play()
               end
               block:SetPickMode(2) -- Polygon
               block:SetCollisionType(2)
               block:SetShape(Shape:Box())
               block:SetRotation(Vec3(0,0,0), true)
               block = nil            
           end
    
           -- Release the block
           if window:MouseHit(1) then -- left mouse button
               if pickinfo.entity:GetKeyValue("name") == "Block" then
                   System:Print("Release")
                   pickinfo.entity:Release()
                   if pickSnd ~= nil then
                       pickSnd:Play()
                   end
               end
    
           end
       else -- Not in blockMode, release the block
           if block ~= nil then    
               block:Release()
               block = nil
           end
       end
    end
    
    
    function Script:PostRender(context)
       if reticleOptic ~= nil then
           context:SetColor(1,1,1,1)
           context:SetBlendMode(Blend.Alpha)        
           context:DrawImage(reticleOptic, context:GetWidth()/2-32, context:GetHeight()/2-32, 64, 64)
           context:SetBlendMode(Blend.Solid)
       end    
    end
    

  10. @shadmar - After you mentioned it, I started looking deeper into my prefab and the Leadwerks collision rules. I have made a little progress. I swapped my CSG block for a basic blender cube, and I'm now setting SetPickMode(0) and SetCollisionType(4) on the instantiated prefab so that it won't be picked while positioning for placement. I've adjusted my camera picks to use collision type to (2), and after I place a block I set SetPickMode(1) and SetCollisionType(2) so that it should be pickable again. Once a block is placed however, I can collide with it when walking up to it or jumping on top of it with the FPSPlayer, but I still can't camera pick the placed blocks. I have the exact same scenario using the CSG cube prefab after SetPickMode and SetCollisionType adjustments, the collider stops me from walking through it, but I can't pick it from the camera.

     

    These pick failure are what I was perceiving as Key/Value failures. If I place an instance of my prefab in the scene at design time, I can pick it at runtime and read the Key/Value, but not when instantiated during runtime. I tried adding world:Update and world:Render() after block placement just in case some physics update was necessary, but it had no effect.

     

    So it seems something must be required to commit pickmode and collisiontype changes at runtime, but I can't seem to figure out what.

     

    The current state of my script:

    Script.player = nil --entity "Player"
    
    window = Window:GetCurrent()
    world = World:GetCurrent()
    context = Context:GetCurrent()
    pickradius = 0.1
    block = nil
    blockMode = false
    pickinfo = nil
    mousePos = nil
    
    function Script:Start()
       pickinfo = PickInfo()
    end
    
    function Script:UpdateWorld()
       mousePos = window:GetMousePosition()
    
       -- Toggle blockMode
       if window:KeyHit(Key.ControlKey) then
           if blockMode == false then
               blockMode = true
           else
               blockMode = false
           end
       end
    
       -- blockMode
       if blockMode == true then
           -- Load a new block
           if block == nil then
               block = Prefab:Load("Prefabs/CM/Cube.pfb")
               block:SetPickMode(0) -- ignore 
               block:SetCollisionType(4) 
               block:SetKeyValue("name","Block") 
           end
    
           -- Position the block grid aligned and normal offset
           if block ~= nil then
               if (self.player.script.camera:Pick(mousePos.x, mousePos.y, pickinfo, pickradius, true, 2)) then
                   block:SetPosition(Vec3(math.floor(pickinfo.position.x), 
                       math.floor(pickinfo.position.y), 
                       math.floor(pickinfo.position.z)) + 
                       Vec3(pickinfo.normal.x, pickinfo.normal.y, pickinfo.normal.z)) 
               end
           end
    
           -- Place the block
           if window:MouseHit(2) then -- right mouse button
               block:SetPickMode(1) -- sphere
               block:SetCollisionType(2)
               block = nil
           end
    
           -- Debug
           if pickinfo ~= nil then
               if pickinfo.entity ~= nil then
                   System:Print("pickinfo: " .. pickinfo.entity:GetKeyValue("name"))
               end
           end
    
           -- Release the block
           if window:MouseHit(1) then -- left mouse button
               if (self.player.script.camera:Pick(mousePos.x, mousePos.y, pickinfo, pickradius, true, 2)) then 
                   if pickinfo.entity:GetKeyValue("name") == "Block" then
                       pickinfo.entity:Release()
                   end
               end
           end
       else -- Not in blockMode, release the block
           if block ~= nil then 
               block:Release()
               block = nil
           end
       end
    end
    

  11. @Aggor - yes the GetKeyValue() with upper case "Name" was a test, I tried upper and lower, they both produce the same error.

     

    @Haydenmango - Thanks, I'll try GetClass() and GetClassName() out.

     

    @Guppy - This sounds great because it would allow me to categories everything, and in my case I really only need a bool check, but can you spot anything I'm doing wrong with the code above, and why it errors:

     

    I instantiate the prefab, then set a key/value pair with name/Block

    block = Prefab:Load("Prefabs/CM/Block.pfb")
    block:SetKeyValue("name","Block")
    

     

    then, in the pickinfo I'm attempting to read the key/value pair

    System:Print(pickinfo.entity:GetKeyValue("name"))
    

     

    But the Print is producing this error: argument #3 is 'string'; '[no object]' expected.

     

    Thanks guys!

  12. Let me ask about entity identification another way. If I have a collision with an entity, what is the best way to distinguish the entity from another? For example: instantiated blocks have the name "Block" and the ground the blocks sit on is a CSG with the name "Ground". If I want to Release() blocks, but not the ground, I need to check the collision entity to determine it's a block and to Release it, or if it's the ground and to ignore the collision. Should I use the name of the entity (how do I get this), does Leadwerks have a layer system that I can place items on and check if the collision entity is on that layer, or maybe place a script on the ignore items and check for the type?

     

    Thanks

  13. I watched Josh's video importing the monster truck to have the shapes automatically generated, but I wasn't sure how that would work in blender since you can't have multiple items with the same name in blender. Unless Leadwerks is just ignoring iterative numbers after the [Collision] name.

     

    I got this working using the above method, mostly just because I wanted to understand it a bit better, but I'll also try it the other way just to test the result.

     

    Thanks!

  14. I have created a small building model in blender and included a very low polly version of it for use as a physics shape, but I can't figure out how to make a physics shape out of it in Leadwerks. [save as Shape] is greyed out in the scene browser when I try to right click on the mesh.

     

    Any help is appreciated,

    Mike

  15. I'm familiarizing myself with Leadwerks and so I have a simple test map that lets me place block prefabs like Minecraft.

     

    How can I retrieve the name from a pickinfo.entity?

     

    I tried the following, but it throws an error in Print in the window:MouseDown(1) check: (argument #3 is 'string'; '[no object]' expected.)

    function Script:UpdateWorld()
       if block == nil then
           block = Prefab:Load("Prefabs/CM/Block.pfb")
           block:SetKeyValue("name","Block")
           block:SetCollisionType(Collision.Prop)
       end
    
       local pickinfo = PickInfo()
       local mousePos = window:GetMousePosition()
       if (self.player.script.camera:Pick(mousePos.x, mousePos.y, pickinfo, pickradius, true)) then
           block:SetPosition(Vec3(math.floor(pickinfo.position.x),
               math.floor(pickinfo.position.y),
               math.floor(pickinfo.position.z)) +
               Vec3(pickinfo.normal.x, pickinfo.normal.y/2, pickinfo.normal.z))
       end
    
       if window:MouseDown(2) then -- Place the block
           block = nil
       end
    
       if window:MouseDown(1) then -- Delete the block
           if pickinfo ~= nil then
               if pickinfo.entity ~= nil then
                   System:Print(pickinfo.entity:GetKeyValue("name"))
               end
               --if pickinfo.entity:GetKeyValue("Name") == "Block" then
               -- pickinfo.entity:Release()
               --end
           end
       end
    end
    

     

    The other issue I'm having is that the placed prefabs have no physics collision.

     

    Thanks,

    Mike

  16. Looks like my duplicated cube had a duplicate of the script and the Camera was not bound to the exposed entity property.

     

    Removing the script on the second cube, and removing the Vec3 cleared the errors.

     

    I moved my self.right setter to the Start function.

     

    Thanks for helping, sorry for the Leadwerks noob mistakes!

  17. That solved the raycast problem, But I'm still having issues drawing the line for debugging. I'm getting an error with no error message on the following line:

    local pos = self.camera:Project(Vec3(self.position)) 

     

    I have the camera defined outside the function as:

    Script.camera=Entity--Entity

    And I linked the scene camera to this property in the editor.

  18. [self.right] is defined outside of the function as:

     

    Script.right=Vec3(1, 0, 0)--Vec3

     

    I found the problem, I had accidentally used a lowercase in the [pickInfo] variable in the Pick function. It's working now.

     

    Thanks

    • Upvote 1
  19. I'm trying to translate my raycasting experience in Unity and Blender GE to Leadwerks, but I'm having a hard time connecting the dots. My test scene includes one cube on the ground, and another cube next to the first (on X axis) and raised above the ground and above the height of the ground cube so that when the game starts, the raised cube falls next to the ground cube. I have a lua script attached to the ground cube and I'm trying to cast a ray from the ground cubes position to a position farther down the x axis so that the raised cube will intersect when it falls.

     

    This is my code in the UpdateWorld function. I get an blank error window. I'm very inexperienced with Leadwerks, so I may be going about it all wrong, but this is what I've gathered from the docs.

     

    Thanks for any help you can provide.

     

    function Script:UpdateWorld()
    self.position = self.entity:GetPosition()
    self.right = Vec3(self.position.x + self.right.x, self.position.y, self.position.z);
    
    local pickInfo = PickInfo()
    local clear = true
    local world = World:GetCurrent()
    local context = Context:GetCurrent()
    
    local pos = self.camera:Project(Vec3(self.position))
    local pRight = self.camera:Project(Vec3(self.right))
    context:DrawLine(pos.x, pos.y, pRight.x, pRight.y)
    
    if (world:Pick(self.position, self.right, pickinfo, 0.0, true)) then
    clear= false
    end
    end
    

  20. I bought the Steam Indie edition because I wanted to start learning the engine, but I ultimately want the C++ access that's included in SE, and I would like to run the Linux version once all the kinks are worked out. The Steam version is currently Windows only, is the Linux version headed for Steam and will my license grant me access to it when it becomes available? Can I add my Steam license to the Client Area on my leadwerks.com account page?

     

    Thanks!

×
×
  • Create New...