Jump to content

Search the Community

Showing results for tags 'tutorial'.

  • Search By Tags

    Type tags separated by commas.
  • Search By Author

Content Type


Blogs

  • Development Blog
  • Canardian's Blog
  • Beyond Civilization Blog Ext
  • Tyler's Blog
  • macklebee's Blog
  • B-Byrnes' Blog
  • Marleys Ghost's Blog
  • omid3098's Blog
  • Richardsimpo123456's Blog
  • DJDD's Blog
  • Rick's Blog
  • --
  • xtreampb's Blog
  • Economically Disadvantaged
  • klepto2's Blog
  • Old Blog
  • Chris Paulson's Blog
  • Davaris' Blog
  • nil
  • Rekindled Phoenix's Blog
  • Flexman's Blog
  • Kattemaksu Online
  • Marcousik's Creations Blog
  • EVE LBS Studio
  • Rendering puzzles
  • Screen Size Utility
  • Niosop's Blog
  • 1299 RTS Game Project
  • Blitzbat's Blog
  • gordonramp's Blog
  • Andy Gilbert's Blog
  • Marcus' Blog
  • JornAggror Blog
  • diedir's Blog
  • wayneg's Blog
  • Masterxilo's Blog
  • Dave Lee's Blog
  • peubuy's blog
  • OD Arts -Leadwerks Blog
  • The progression......
  • Ultra Software Company Blog
  • The Progression
  • Pancake's Blog
  • Test Blog
  • BLaBZ Blog
  • Pure³d's Blog
  • dreamhead Blog
  • RVL's Blog
  • DB's Blog
  • Toxin Games Development Blog
  • CombatHelo Blog (RSS Import)
  • Foolish's Blog
  • ZioRed's Corner
  • Toxin Games Twitter
  • Shard - Third Initiative
  • Shard's Blog
  • Soamp's Blog
  • Soamp's Blog
  • Laurens' Blog
  • JT`s warehouse district
  • Kennar's Blog
  • KiteFuchs' Blog
  • KiteFuchs' Blog
  • Rachel's Dev-Blog
  • Eagle's Blog
  • zaphos' Blog
  • please delete this blog
  • Afke's Blog
  • Richard Simpson
  • knowledgegranted's Blog
  • EdzUp(GD)'s Blog
  • aGameLife's Kelasel MMORPG Blog
  • tournamentdan's Blog
  • Beyond Civilization Blog
  • smashthewindow
  • AnniXa's Blog
  • AnniXa's Blog
  • Elemental Development
  • DigitalHax Blog
  • Aria's Blog
  • Strogg76's Blog
  • Clackdor's Blog
  • Leadwerks Project Status
  • simpleprogrammer's Blog
  • Pathfinding in LE.2.x
  • Naughty Alien's Blog
  • smashthewindow's Blog
  • Ali Salehi's Blog
  • Jardar's Blog
  • Chris Vossen's Development Blog
  • Scarlet Thread Studios' Blog
  • Kronos' Blog
  • Benton's Blog
  • ChrisV's Blog
  • tjheldna's Blog
  • shadmar's Blog
  • 3D Masons, LLC
  • Andy Gilbert's Enviro Models
  • ParaToxic's Blog
  • NarkLord's Blog
  • ChrisMAN's Blog
  • ChrisMAN's Blog
  • CGMan's Blog
  • The Game
  • Chris Tutorials
  • Leadwerks 3 Experience
  • An Alien Saga
  • klepto2 & Leadwerks 3
  • Inside the mind of eternal insomniac
  • josk's Blog
  • Shader Development in Leadwerks 3.1
  • 3D Coat : Column game making of
  • Einlander's Blog
  • Ginger George's Blog
  • I have a problem
  • Michael_J's Blog
  • nasamydifol's Blog
  • Digman's Blog
  • noesisGUI
  • SavageDogg38's Blog
  • Built from Ruins
  • Remaining Days
  • test_external_blog
  • The Hunt For Food Blog
  • Crazy Minnow Studio
  • CrazyMinnowStudio
  • Guppy's Blog
  • Playing Online
  • Evayr's Blog
  • DerRidda's Blog
  • Karl's Blog
  • whiterabbit's Blog
  • Tinyboss Games
  • abendkleider's Blog
  • sacguccireplica's Blog
  • Arena
  • Imchasinyou's Blog
  • xtom's Blog
  • Lua is better than you think.
  • mdgunn's Blog
  • Crime Closer
  • lxFirebal69xl's Blog
  • Wedmer's Blog
  • Lockdown, going forward.
  • Pump-Action Captain
  • Igor's Blog
  • Dead Anyway
  • Runenrise and more
  • reepblue's Blog
  • Slippy's Corner
  • LUA Musings
  • severjack's Blog
  • mikeporter's Blog
  • miko93's Blog
  • Megalocerous' Blog
  • lxFirebal69xl's Blog
  • aiaf's Blog
  • Lostghbear's Blog
  • echo $BLOG_NAME > blog_title.tmpl
  • johnadam111's Blog
  • Dwarf Beard
  • burgelkat's Blog
  • Charrua's Blog
  • peterpaul's Blog
  • joshmathews' Blog
  • Martin Kearl's Blog
  • Brutile's blog
  • tipforeveryone's Blog
  • Glushchenko Blog
  • Express Lab Games Blog
  • Blueapples' Blog
  • DooMAGE's Blog
  • Structura devblog
  • UltraEngine - Experiences, add-ons and other Stuff
  • martyj's Blog
  • Dragonfreak's Blog
  • Brutile's Blog
  • assigmenthelp
  • Case Study Assignment Help
  • How to deal with bad grade ?
  • How to deal with bad grade ?
  • GameDev Blog
  • devcjohnson's Blog
  • devcjohnson's Blog
  • THE WHAT? Blog
  • The Demurian Scribe
  • GUI Editor
  • GUI Tutorial
  • noob_shaders
  • The Seventh World
  • Phodex Games Blog
  • Leadwerks VS Source 2
  • Work in Progress - Scifi PBR Media
  • [C++] First Player game start
  • The Blog of Yue
  • Snowboarding Development Blog
  • Ocean: Rendering in Leadwerks 4
  • Game Ready Maps
  • Ultra App Kit (Advanced Custom Widgets)
  • Poking around
  • Blender tutorials
  • Usefull Scripts & Components
  • Thirsty Panther
  • Ultimate Action Game Controller
  • Ultra Tutorials

Forums

  • Software
    • General Discussion
    • Programming
    • Game Artwork
    • Showcase
    • Suggestion Box
    • Bug Reports
  • Addons
    • Extensions & Plugins
    • Components
    • Addon Development
  • Platforms
    • Windows
    • Linux
    • macOS

Categories

  • Streams and Events
  • Tutorials
  • Games
  • Work in Progress

Categories

  • Components
  • Effects
  • Extensions
  • Materials
    • Asphalt
    • Brick
    • Concrete
    • Debris
    • Effects
    • Fabric
    • Ground
    • Marble
    • Metal
    • Organic
    • Plaster
    • Rock
    • Roof
    • Sand
    • Snow
    • Surface Imperfections
    • Tile
    • Wood
  • Models
    • Animals & Creatures
    • Architecture
    • Food
    • Machinery
    • Plants and Vegetation
    • Props
    • Vehicles
    • Tools
  • Scenes
  • Skyboxes
  • Sound
  • Tools

Find results in...

Find results that contain...


Date Created

  • Start

    End


Last Updated

  • Start

    End


Filter by number of...

Joined

  • Start

    End


Group


Location

  1. Prerequisites https://www.ultraengine.com/learn/luasetup?lang=lua Also Lua extension is quite useful for VS Code, if you don't mind Tencent. Map Create a simple map call start.ultra with a brush as floor and a Empty aka pivot with FPSPlayer component How to do it: Now you can press "F5" in the editor, or select "Game" then "run" to run your game to just made map: You can add skybox in Edit > World Settings (at top buttons in the Editor) by choosing skybox.dds from Materials\Environment\Default Main menu, loading screen and GUI Create a simple menu with couple brushes and camera and name this map menu.ultra Now open main.lua. For that open Project tab in top right corner, select root project folder and double click on Open the VSCode.bat file. If this fails make sure you have setup Visual Studio Code correctly https://www.ultraengine.com/learn/luasetup?lang=lua Select all i nfile and delete it from VS Code. Now paste there folllow code with just a Loading screen, almost without anything else and save: -- local before variable means it will be avaiable only in current scope (inside script, funtion, cycle or condition body) -- loading screen vars local loadingWorld = nil local loadingCamera = nil local loadingText = nil local loadingBackground = nil -- for using in main loop local currentWorld = nil local currentUi = nil local displays = GetDisplays() -- You can WINDOW_FULLSCREEN to styles to make game fullscreen, 3rd and 4th are resolution size window = CreateWindow("Ultra Engine", 0, 0, 1280, 720, displays[1], WINDOW_CENTER | WINDOW_TITLEBAR) -- Create a framebuffer, needed for rendering framebuffer = CreateFramebuffer(window) font = LoadFont("Fonts/arial.ttf"); loadingWorld = CreateWorld(); local centerX = framebuffer:GetSize().x * 0.5 local centerY = framebuffer:GetSize().y * 0.5 local labelHeight = framebuffer:GetSize().y * 0.2 loadingBackground = CreateSprite(loadingWorld, framebuffer.size.x, framebuffer.size.y) loadingBackground:SetColor(0.2, 0.2, 0.2); loadingBackground:SetRenderLayers(2); loadingText = CreateSprite(loadingWorld, font, "LOADING", labelHeight, TEXT_CENTER | TEXT_MIDDLE) loadingText:SetPosition(centerX, centerY + labelHeight * 0.5, 0) -- 0 layer - no render, 1 - default render, we will use 2 for UI and sprites loadingText:SetRenderLayers(2) -- Creating camera for sprites, which needs to be orthographic (2D) for UI and sprites if they used as UI loadingCamera = CreateCamera(loadingWorld, PROJECTION_ORTHOGRAPHIC); loadingCamera:SetPosition(centerX, centerY, 0); -- camera render layer should match with stuff that you want to be visible for this camera. RenderLayers is a bit mask, so you can combine few layers, but probably you don't need it in most cases loadingCamera:SetRenderLayers(2) currentWorld = loadingWorld -- simple minimum game loop while window:Closed() == false do -- Garbage collection step collectgarbage() -- getting all events from queue - input, UI etc. while (PeekEvent()) do local event = WaitEvent() -- You need to do it for UI in 3D scene if (currentUi) then currentUi:ProcessEvent(event) end end if (currentWorld) then -- Update game logic (positions, components etc.). By default 60 HZ and not depends on framerate if you have 60+ FPS currentWorld:Update() -- 2nd param is VSync (true by default), 3rd is fps limit. Can by changed dynamically. currentWorld:Render(framebuffer) end end Now if we start a game we will see this loading screen: And once we have a screen we can create a menu to load in. Create MainMenu.lua in Source folder. To do it in Visual Studio Code select "File" then select "New file". Type in "MainMenu.lua" and hit return. A dialog box will open asking where you want to save this file. It should open in the source folder by default but if it dosen't navigate to the source folder and hit return. Paste in the following content for this file and save: local function NewGameButtonCallback(Event, Extra) --this overload currently is not working --EmitEvent(EVENT_GAME_START, nil, 0, 0, 0, 0, 0, nil, "start.ultra") EmitEvent(EVENT_GAME_START) return true end local function ExitButtonCallback(Event, Extra) --to close application os.exit() return true end local function InitMainMenu(mainMenu) mainMenu.world = CreateWorld(); mainMenu.scene = LoadMap(mainMenu.world, "Maps/menu.ultra") --Create user interface local frameSize = framebuffer:GetSize(); mainMenu.ui = CreateInterface(mainMenu.world, font, frameSize) mainMenu.ui:SetRenderLayers(2); --to make backgrount transparent mainMenu.ui.background:SetColor(0.0, 0.0, 0.0, 0.0) --Create camera for GUI mainMenu.uiCamera = CreateCamera(mainMenu.world, PROJECTION_ORTHOGRAPHIC) mainMenu.uiCamera:SetPosition(frameSize.x * 0.5, frameSize.y * 0.5, 0); mainMenu.uiCamera:SetRenderLayers(2); --for correct rendering above 3D scene mainMenu.uiCamera:SetClearMode(CLEAR_DEPTH); --Menu buttons local newGameButton = CreateButton("New game", frameSize.x / 2 - 100, 125, 200, 50, mainMenu.ui.background); ListenEvent(EVENT_WIDGETACTION, newGameButton, NewGameButtonCallback); local exitButton = CreateButton("Exit", frameSize.x / 2 - 100, 200, 200, 50, mainMenu.ui.background); ListenEvent(EVENT_WIDGETACTION, exitButton, ExitButtonCallback); end --functions should be declared after another function that this fucntion uses function CreateMainMenu() local mainMenu = {} InitMainMenu(mainMenu) return mainMenu end Let's get back to main.lua. We need to import main menu script and custom event ids to top: import "Source/MainMenu.lua" --custom events ids EVENT_GAME_START = 1001 EVENT_MAIN_MENU = 1002 Now add after "local currentUi = nil" menu var and callback fuctions for events: framebuffer = nil local menu = nil local function StartGameEventCallback(Event, Extra) --nothing just for now return true; end --function should be declared after vars that this function uses local function MainMenuEventCallback(Event, Extra) menu = CreateMainMenu(); --switching current render and update targets for loop currentWorld = menu.world; currentUi = menu.ui; return true; end Put this above main loop: --to show Loading screen before Main Menu loadingWorld:Render(framebuffer); --ListenEvent are needed to do something in callback function when specific even from specfic source (or not, if 2nd param is nil) emitted ListenEvent(EVENT_GAME_START, nil, StartGameEventCallback); ListenEvent(EVENT_MAIN_MENU, nil, MainMenuEventCallback); --let's try it out! EmitEvent(EVENT_MAIN_MENU) Just in case if something one wrong, current main.lua main.lua We need to modify FPSPlayer component just a little bit. Via Editor you can find it by selecting "Project" ( Top right of the editor screen), select "Source", select "Components", select "Player". Double click "FPSPlayer.lua". Add to its top to other vars a new one (24th line to be precisely) FPSPlayer.doResetMousePosition = true And new condition for mouse position reset in FPSPlayer.lua in Update() at 286 line or find thine line with Ctrl-F and past to search field "window:SetMousePosition(cx, cy)" if doResetMousePosition then window:SetMousePosition(cx, cy) end One big thing left - a game to play. Add Game.lua to project at Source folder: local function GameMenuButtonCallback(Event, Extra) if (KEY_ESCAPE == Event.data and Extra) then local game = Extra local isHidden = game.menuPanel:GetHidden() game.menuPanel:SetHidden(not isHidden) if isHidden then window:SetCursor(CURSOR_DEFAULT) else window:SetCursor(CURSOR_NONE) end if (game.player ~= nil) then --to stop cursor reset to center when menu on game.player.doResetMousePosition = not isHidden end end return false end local function MainMenuButtonCallback(Event, Extra) EmitEvent(EVENT_MAIN_MENU) return true end local function ExitButtonCallback(Event, Extra) os.exit() return true end local function InitGame(game, mapPath) game.world = CreateWorld(); game.scene = LoadScene(game.world, mapPath) for k, entity in pairs(game.scene.entities) do local foundPlayer = entity:GetComponent("FPSPlayer") if (foundPlayer ~= nil) then game.player = foundPlayer; break; end end --Create user interface for game menu local frameSize = framebuffer:GetSize() game.ui = CreateInterface(game.world, font, frameSize) game.ui:SetRenderLayers(2) game.ui.background:SetColor(0.0, 0.0, 0.0, 0.0) game.uiCamera = CreateCamera(game.world, PROJECTION_ORTHOGRAPHIC) game.uiCamera:SetPosition(frameSize.x * 0.5, frameSize.y * 0.5, 0) game.uiCamera:SetRenderLayers(2); game.uiCamera:SetClearMode(CLEAR_DEPTH); --widgets are stays without extra pointers because parent widet, game.ui.background in this case, keep them --to remove widget you should do widget:SetParent(nil) game.menuPanel = CreatePanel(frameSize.x / 2 - 150, frameSize.y / 2 - 125 / 2, 300, 250, game.ui.background) local menuButton = CreateButton("Main menu", 50, 50, 200, 50, game.menuPanel); ListenEvent(EVENT_WIDGETACTION, menuButton, MainMenuButtonCallback); local exitButton = CreateButton("Exit", 50, 150, 200, 50, game.menuPanel); ListenEvent(EVENT_WIDGETACTION, exitButton, ExitButtonCallback); --we don't need game menu on screen while playing game.menuPanel:SetHidden(true); --and we will need it once hitting Esc button ListenEvent(EVENT_KEYUP, window, GameMenuButtonCallback, game); end --functions should be declared after another function that this fucntion uses function CreateGame(mapPath) local game = {} InitGame(game, mapPath) return game end Add new Game include and global var to main.lua: import "Source/Game.lua" local game = nil Update function callbacks at 24 line: local function StartGameEventCallback(Event, Extra) --destroying a main menu menu = nil --to show loading screen loadingWorld:Render(framebuffer) if Event.text ~= nil and Event.text ~= "" then --in lua .. used for string concatenation game = CreateGame("Maps/" .. Event.text); else game = CreateGame("Maps/start.ultra"); end --switching current render and update targets for loop currentWorld = game.world currentUi = game.ui return true; end --function should be declared after vars that this function uses local function MainMenuEventCallback(Event, Extra) --destroying a game instance if one existed game = nil --to show loading screen loadingWorld:Render(framebuffer) menu = CreateMainMenu() --switching current render and update targets for loop currentWorld = menu.world; currentUi = menu.ui; return true; end And in the end we have a game with own menu: All created and modified classes: LuaMenuGameLoad.zip Repository: https://github.com/Dreikblack/LuaTutorialProject/tree/menu-loading-screen-and-gui
  2. In this tutorial we will make a newcomponent, which will be moving an entity to way points and movement start will be activated by trigger zone Let's start with making WayPoint component: In the Ultra Editor click plus button in Project tab: Now open Visual Studio Code. Open WayPoint.json "properties" is a list of component's fields avaible for edit in the Editor "name" - actual name of property that will be used in code later "label" - just a name to display in the Editor "value" - initial value that property will have after map load by default. Can be changed in the Editor for specific entity. "options" - allows to choose int value in Combo Box in the Editor. First option - 0 value Default value here also defines type of this property. New component made via editor have all possible types. Replace WayPoint.json content with: { "component": { "properties": [ { "name": "nextPoint", "label": "Next point", "value": null }, { "name": "doStayOnPoint", "label": "Do stay on point", "value": false } ] } } nextPoint - another WayPoint, where platform will move to once reach this one doStayOnPoint - wait for command before moving to next WayPoint Take a note that the Editor sees only json which could be same for LUA and C++ projects which allows to work on same map even if people have different engine versions (Pro/Standard) or make a level before programming components. Replace WayPoint.lua content with: WayPoint = {} -- name should always match class name for correct component work WayPoint.name = "WayPoint" WayPoint.nextPoint = nil -- wait for command before moving to next WayPoint WayPoint.doStayOnPoint = false -- Start is called when Load() of all components was called already function WayPoint:Start() end -- will be called on map load function WayPoint:Load(properties, binstream, scene, flags, extra) -- internally entity saves in the Editor as String unique id -- can be empty if this way point is final if type(properties.nextPoint) == "string" then for _, entity in ipairs(scene.entities) do if properties.nextPoint == entity:GetUuid() then self.nextPoint = entity break end end -- self.nextPoint = scene:GetEntity(properties.nextPoint) if type(properties.doStayOnPoint) == "boolean" then self.doStayOnPoint = properties.doStayOnPoint end end return true end -- Can be used to save current component state on map save function WayPoint:Save(properties, binstream, scene, flags, extra) if self.nextPoint ~= nil then properties.nextPoint = self.nextPoint:GetUuid() properties.doStayOnPoint = self.doStayOnPoint; end return true end -- Can be used to get copy of this component function WayPoint:Copy() local t = {} local k local v for k, v in pairs(self) do t[k] = v end return t end -- needed for correct work, when loaded from a map RegisterComponent("WayPoint", WayPoint) return WayPoint Let's create our floating object component and call it WayMover WayMover.json: { "component": { "properties": [ { "name": "moveSpeed", "label": "Move Speed", "value": 4.0 }, { "name": "nextPoint", "label": "Next point", "value": null }, { "name": "doDeleteAfterMovement", "label": "Del after move", "value": false } ], "inputs": [ { "name": "DoMove" } ], "outputs": [ { "name": "EndMove" } ] } } moveSpeed - how fast entity will move to way point doDeleteAfterMovement - auto remove entity when it's reach final waypoint. Can be used for door, that goes into walls or floor inputs - it's commands for components, that usually triggered by another components via flowgrough outputs - commands that component sends to other components inputs via FireOutputs("EndMove"); in the component code WayMover.lua: WayMover = {} -- name should always match class name for correct component work WayMover.name = "WayMover" WayMover.moveSpeed = 4.0 WayMover.isMoving = false WayMover.nextPoint = nil WayMover.scene = nil function WayMover:Copy() local t = {} local k local v for k, v in pairs(self) do t[k] = v end return t end -- will be called on map load function WayMover:Load(properties, binstream, scene, flags, extra) if type(properties.moveSpeed) == "number" then self.moveSpeed = properties.moveSpeed end if type(properties.isMoving) == "boolean" then self.isMoving = properties.isMoving end if type(properties.doDeleteAfterMovement) == "boolean" then self.doDeleteAfterMovement = properties.doDeleteAfterMovement end if type(properties.nextPoint) == "string" then for _, entity in ipairs(scene.entities) do if properties.nextPoint == entity:GetUuid() then self.nextPoint = entity break end end -- self.nextPoint = scene:GetEntity(properties.nextPoint) -- need scene for removing entity on doDeleteAfterMovement condition self.scene = scene return true end end -- Can be used to save current component state on map save function WayMover:Save(properties, binstream, scene, flags, extra) if self.nextPoint ~= nil then properties.nextPoint = self.nextPoint:GetUuid() properties.doStayOnPoint = self.doStayOnPoint; end properties.moveSpeed = self.moveSpeed; properties.isMoving = self.isMoving; properties.doDeleteAfterMovement = self.doDeleteAfterMovement; return true end function WayMover:DoMove() self.isMoving = true end function WayMover:MoveEnd() local doStay = false if (self.nextPoint ~= nil) then doStay = self.nextPoint:GetComponent("WayPoint").doStayOnPoint self.nextPoint = self.nextPoint:GetComponent("WayPoint").nextPoint end if (doStay or self.nextPoint == nil) then self.isMoving = false; self:FireOutputs("EndMove") -- deleting entity if need to, after reaching final way point if (not doStay and self.nextPoint == nil and self.doDeleteAfterMovement and self.scene ~= nil) then --commented out this code for now until bind for RemoveEntity will added --self.scene:RemoveEntity(self.entity) end end end function WayMover:Update() if (not self.isMoving) then return; end local wayPoint = self.nextPoint if (self.entity == nil or wayPoint == nil) then return end --60 HZ game loop, change to own value if different to keep same final speed local speed = self.moveSpeed / 60.0 local targetPosition = wayPoint:GetPosition(true) --moving to point with same speed directly to point no matter which axis local pos = self.entity:GetPosition(true); local distanceX = Abs(targetPosition.x - pos.x); local distanceY = Abs(targetPosition.y - pos.y); local distanceZ = Abs(targetPosition.z - pos.z); local biggestDelta = distanceZ; if (distanceX > distanceY and distanceX > distanceZ) then biggestDelta = distanceX; elseif (distanceY > distanceX and distanceY > distanceZ) then biggestDelta = distanceY; end local moveX = MoveTowards(pos.x, targetPosition.x, speed * (distanceX / biggestDelta)); local moveY = MoveTowards(pos.y, targetPosition.y, speed * (distanceY / biggestDelta)); local moveZ = MoveTowards(pos.z, targetPosition.z, speed * (distanceZ / biggestDelta)); self.entity:SetPosition(moveX, moveY, moveZ) if (self.entity:GetPosition(true) == targetPosition) then self:MoveEnd() end end -- needed for correct work, when loaded from a map RegisterComponent("WayMover", WayMover) return WayMover Now we can use just made component in practice. One of things that can be made is door or secret wall activated by player actions and this door will move a little bit inward and then to the side inside of wall. After that invisible now door will be removed. Create a walls with a empty place between them. Create couple of Empty/pivots and attach WayPoints to them. First WayPoint place a same place where door will be, but offset a bit deep into. In Scene tab grab and drag 2nd WayPoint to Nex Point field of 1st WayPoint. Place 2nd WayPoint insde of the wall. Create a door between walls. Attach WayMover component to it. Grab and drag 1st WayPoint to door's WayMover Next Point field. Enable "Del after Move" in WayMover component Create a box before door, make its collision type a trigger: Add Collision Trigger component to it. Open Flowgraph (2nd button at left side of the Editor). Drag and Drop trigger and door to it from Scene tab. In different order, but same result in video format: Result should looks something like that in game: In fast debug mode it might crash at this moment for unkown reason. Use Full Debug or Run mode. Project files: LuaExample2.zip Repository: https://github.com/Dreikblack/LuaTutorialProject/tree/2-making-and-using-components
  3. In this tutorial we will make a newcomponent, which will be moving an entity to way points and movement start will be activated by trigger zone Let's start with making WayPoint component: In the Ultra Editor click plus button in Project tab: Now open Visual Studio. Refresh Soution Editor if it was already open to see new component files in Source/Component/Logic folder. Include into project WayPoint.h and WayPoint.cpp. Add WayPoint include to Source/ComponentSystem.h #include "Components/Logic/WayPoint.h" In RegisterComponents() add: RegisterComponent<WayPoint>(); You might do RegisterComponent first and add include with VS help Open WayPoint.json "properties" is a list of component's fields avaible for edit in the Editor "name" - actual name of property that will be used in code later "label" - just a name to display in the Editor "value" - initial value that property will have after map load by default. Can be changed in the Editor for specific entity. "options" - allows to choose int value in Combo Box in the Editor. First option - 0 value Default value here also defines type of this property. New component made via editor have all possible types. Replace WayPoint.json content with: { "component": { "properties": [ { "name": "nextPoint", "label": "Next point", "value": null }, { "name": "doStayOnPoint", "label": "Do stay on point", "value": false } ] } } nextPoint - another WayPoint, where platform will move to once reach this one doStayOnPoint - wait for command before moving to next WayPoint Take a note that the Editor sees only json which could be same for LUA and C++ projects which allows to work on same map even if people have different engine versions (Pro/Standard) or make a level before programming components. Replace WayPoint.h content with: #pragma once #include "UltraEngine.h" using namespace UltraEngine; class WayPoint : public Component { protected: //another WayPoint's entity, where platform will move to once reaching this one //it should be weak pointer for avoiding circular dependency when entities can't be removed from scene because they keep shared pointers to each other std::weak_ptr<Entity> nextPoint; public: //wait for command before moving to next WayPoint bool doStayOnPoint; WayPoint(); //override specifier ensures that the method is virtual and is overriding a virtual function from a base class //it means that this class method will be called even if class instance was casted to base class //it allows to change class behaviour from base one //Start is called when Load() of all components was called already void Start() override; //will be called on map load bool Load(table& t, shared_ptr<Stream> binstream, shared_ptr<Map> scene, const LoadFlags flags, shared_ptr<Object> extra) override; //Can be used to save current component state on map save bool Save(table& t, shared_ptr<Stream> binstream, shared_ptr<Map> scene, const SaveFlags flags, shared_ptr<Object> extra) override; //get next WayPoint's entity shared_ptr<Entity> getNextPoint() const; //can be used to specify what should and what should not be copied to new class instance shared_ptr<Component> Copy() override; }; Replace WayPoint.cpp content with: #pragma once #include "UltraEngine.h" #include "WayPoint.h" using namespace UltraEngine; WayPoint::WayPoint() { //name should always match class name for correct component work name = "WayPoint"; doStayOnPoint = false; } void WayPoint::Start() { //empty for this case } bool WayPoint::Load(table& properties, shared_ptr<Stream> binstream, shared_ptr<Map> scene, const LoadFlags flags, shared_ptr<Object> extra) { //internally entity saves in the Editor as String unique id //can be empty if this way point is final if (properties["nextPoint"].is_string()) { std::string id = properties["nextPoint"]; nextPoint = scene->GetEntity(id); if (properties["doStayOnPoint"].is_boolean()) { doStayOnPoint = properties["doStayOnPoint"]; } } return true; } bool WayPoint::Save(table& properties, shared_ptr<Stream> binstream, shared_ptr<Map> scene, const SaveFlags flags, shared_ptr<Object> extra) { if (nextPoint.lock()) { properties["nextPoint"] = nextPoint.lock()->GetUuid(); properties["doStayOnPoint"] = doStayOnPoint; } return true; } shared_ptr<Entity> WayPoint::getNextPoint() const { return nextPoint.lock(); } shared_ptr<Component> WayPoint::Copy() { return std::make_shared<WayPoint>(*this); } Let's create our floating object component and call it WayMover WayMover.json: { "component": { "properties": [ { "name": "moveSpeed", "label": "Move Speed", "value": 4.0 }, { "name": "nextPoint", "label": "Next point", "value": null }, { "name": "doDeleteAfterMovement", "label": "Del after move", "value": false } ], "inputs": [ { "name": "DoMove" } ], "outputs": [ { "name": "EndMove" } ] } } moveSpeed - how fast entity will move to way point doDeleteAfterMovement - auto remove entity when it's reach final waypoint. Can be used for door, that goes into walls or floor inputs - it's commands for components, that usually triggered by another components via flowgrough outputs - commands that component sends to other components inputs via FireOutputs("EndMove"); in the component code WayMover.h: #pragma once #include "UltraEngine.h" using namespace UltraEngine; class WayMover : public Component { protected: float moveSpeed; bool isMoving; std::weak_ptr<Entity> nextPoint; bool doDeleteAfterMovement; //need scene pointer to remove entity if doDeleteAfterMovement true //should be weak_ptr to avoid circular dependency std::weak_ptr<Map> sceneWeak; public: WayMover(); std::shared_ptr<Component> Copy() override; bool Load(table& properties, shared_ptr<Stream> binstream, shared_ptr<Map> scene, const LoadFlags flags, shared_ptr<Object> extra) override; bool Save(table& properties, shared_ptr<Stream> binstream, shared_ptr<Map> scene, const SaveFlags flags, shared_ptr<Object> extra) override; //CallMethod procceds input signals std::any CallMethod(shared_ptr<Component> caller, const WString& name, const std::vector<std::any>& args) override; void Update() override; //called when reaching next WayPoint void moveEnd(); }; WayMover.cpp: #pragma once #include "UltraEngine.h" #include "WayMover.h" #include "../Logic/WayPoint.h" using namespace UltraEngine; WayMover::WayMover() { name = "WayMover"; moveSpeed = 4.0f; isMoving = false; doDeleteAfterMovement = false; } shared_ptr<Component> WayMover::Copy() { return std::make_shared<WayMover>(*this); } bool WayMover::Load(table& properties, shared_ptr<Stream> binstream, shared_ptr<Map> scene, const LoadFlags flags, shared_ptr<Object> extra) { if (properties["moveSpeed"].is_number()) { moveSpeed = properties["moveSpeed"]; } if (properties["isMoving"].is_boolean()) { isMoving = properties["isMoving"]; } if (properties["doDeleteAfterMovement"].is_boolean()) { doDeleteAfterMovement = properties["doDeleteAfterMovement"]; } if (properties["nextPoint"].is_string()) { std::string id = properties["nextPoint"]; nextPoint = scene->GetEntity(id); } sceneWeak = scene; return Component::Load(properties, binstream, scene, flags, extra); } bool WayMover::Save(table& properties, shared_ptr<Stream> binstream, shared_ptr<Map> scene, const SaveFlags flags, shared_ptr<Object> extra) { properties["moveSpeed"] = moveSpeed; properties["isMoving"] = isMoving; properties["doDeleteAfterMovement"] = doDeleteAfterMovement; if (nextPoint.lock()) { properties["nextPoint"] = nextPoint.lock()->GetUuid(); } return Component::Save(properties, binstream, scene, flags, extra); } std::any WayMover::CallMethod(shared_ptr<Component> caller, const WString& name, const std::vector<std::any>& args) { //start moving by triggering by another component if (name == "DoMove") { isMoving = true; } return false; } void WayMover::Update() { if (!isMoving) { return; } auto entity = GetEntity(); auto wayPoint = nextPoint.lock(); if (!entity || !wayPoint) { return; } //60 HZ game loop, change to own value if different to keep same final speed float speed = moveSpeed / 60.0f; auto targetPosition = wayPoint->GetPosition(true); //moving to point with same speed directly to point no matter which axis auto pos = entity->GetPosition(true); float distanceX = abs(targetPosition.x - pos.x); float distanceY = abs(targetPosition.y - pos.y); float distanceZ = abs(targetPosition.z - pos.z); float biggestDelta = distanceZ; if (distanceX > distanceY && distanceX > distanceZ) { biggestDelta = distanceX; } else if (distanceY > distanceX && distanceY > distanceZ) { biggestDelta = distanceY; } float moveX = MoveTowards(pos.x, targetPosition.x, speed * (distanceX / biggestDelta)); float moveY = MoveTowards(pos.y, targetPosition.y, speed * (distanceY / biggestDelta)); float moveZ = MoveTowards(pos.z, targetPosition.z, speed * (distanceZ / biggestDelta)); entity->SetPosition(moveX, moveY, moveZ); if (entity->GetPosition(true) == targetPosition) { moveEnd(); } } void WayMover::moveEnd() { auto wayPoint = nextPoint.lock(); bool doStay = false; if (wayPoint) { doStay = wayPoint->GetComponent<WayPoint>()->doStayOnPoint; wayPoint = wayPoint->GetComponent<WayPoint>()->getNextPoint(); nextPoint = wayPoint; } if (doStay || !wayPoint) { isMoving = false; FireOutputs("EndMove"); //deleting entity if need to, after reaching final way point if (!doStay && !wayPoint && doDeleteAfterMovement && !sceneWeak.expired()) { auto scene = sceneWeak.lock(); scene->RemoveEntity(GetEntity()); } } } Now we can use just made component in practice. One of things that can be made is door or secret wall activated by player actions and this door will move a little bit inward and then to the side inside of wall. After that invisible now door will be removed. Create a walls with a empty place between them. Create couple of Empty/pivots and attach WayPoints to them. First WayPoint place a same place where door will be, but offset a bit deep into. In Scene tab grab and drag 2nd WayPoint to Nex Point field of 1st WayPoint. Place 2nd WayPoint insde of the wall. Create a door between walls. Attach WayMover component to it. Grab and drag 1st WayPoint to door's WayMover Next Point field. Enable "Del after Move" in WayMover component Create a box before door, make its collision type a trigger: Add Collision Trigger component to it. Open Flowgraph (2nd button at left side of the Editor). Drag and Drop trigger and door to it from Scene tab. In different order, but same result in video format: Result should looks something like that in game: New components and map: NewComponentsTutorFiles.zip On GitHub: https://github.com/Dreikblack/CppTutorialProject/tree/2-making-and-using-components
  4. Prerequisites https://www.ultraengine.com/learn/cppsetup?lang=cpp Install Ultra Engine Pro Check the environment variable ULTRAENGINE (typically "C:\Program Files\Ultra Engine" or if you got Ultra Engine through Steam it will be "C:\Program Files (x86)\Steam\steamapps\common\Ultra Engine Pro"). Install Visual Studio 2022 Community Edition During the installation process, make sure to select the "Desktop development with C++" option Create C++ project with Blank Project template Map Create a simple map call start.ultra with a brush as floor and a Empty aka pivot with FPSPlayer component How to do it: Now in Visual Studio (VS) you can compile and run main.cpp to see how it’s looks in game: You can add skybox in Edit > World Settings (at top buttons in the Editor) by choosing skybox.dds from Materials\Environment\Default Main menu, loading screen and GUI Create a simple menu with couple brushes and camera and name this map menu.ultra main.cpp with a code just for Loading screen almost without anything else: #include "UltraEngine.h" #include "ComponentSystem.h" using namespace UltraEngine; shared_ptr<Window> window; shared_ptr<Framebuffer> framebuffer; //loading screen vars shared_ptr<World> loadingWorld; shared_ptr<Camera> loadingCamera; shared_ptr<Sprite> loadingText; shared_ptr<Sprite> loadingBackground; //for using in main loop shared_ptr<World> currentWorld; shared_ptr<Interface> currentUi; int main(int argc, const char* argv[]) { //Need it to make component from map's entites start working RegisterComponents(); //Computer screens auto displays = GetDisplays(); window = CreateWindow("Ultra Engine Game", 0, 0, 1280, 720, displays[0], WINDOW_CENTER | WINDOW_TITLEBAR); framebuffer = CreateFramebuffer(window); //need a dedicated world to be able render and to stop renedering loading screen wheen needed loadingWorld = CreateWorld(); float centerX = float(framebuffer->GetSize().x) * 0.5f; float centerY = float(framebuffer->GetSize().y) * 0.5f; float labelHeight = float(framebuffer->GetSize().y) * 0.2f; loadingBackground = CreateSprite(loadingWorld, framebuffer->size.width, framebuffer->size.height); loadingBackground->SetColor(0.2, 0.2, 0.2); loadingBackground->SetRenderLayers(2); auto font = LoadFont("Fonts/arial.ttf"); loadingText = CreateSprite(loadingWorld, font, "LOADING", labelHeight, TEXT_CENTER | TEXT_MIDDLE); loadingText->SetPosition(centerX, centerY + labelHeight * 0.5f); //0 layer - no render, 1 - default render, we will use 2 for UI and sprites loadingText->SetRenderLayers(2); //Creating camera for sprites, which needs to be orthographic (2D) for UI and sprites if they used as UI loadingCamera = CreateCamera(loadingWorld, PROJECTION_ORTHOGRAPHIC); loadingCamera->SetPosition(centerX, centerY, 0); //camera render layer should match with stuff that you want to be visible for this camera. RenderLayers is a bit mask, so you can combine few layers, but probably you don't need it in most cases loadingCamera->SetRenderLayers(2); currentWorld = loadingWorld; //simple minimum game loop while (window->Closed() == false) { //getting all events from queue - input, UI etc. while (PeekEvent()) { const Event ev = WaitEvent(); //You need to do it for UI in 3D scene if (currentUi) { currentUi->ProcessEvent(ev); } } if (currentWorld) { //Update game logic (positions, components etc.). By default 60 HZ and not depends on framerate if you have 60+ FPS currentWorld->Update(); //2nd param is VSync (true by default), 3rd is fps limit. Can by changed dynamically. currentWorld->Render(framebuffer); } } //if get here by closing window application will ends/closes return 0; } Now if we start a game we will see this loading screen: Before making new classes it's better to do enable "Show All Files" mode to be able see actual folders in the project: And once we have a screen we can create a menu to load in. But let's get prepared to a future a bit and make custom events. We will need it to use Event system with own events. Add CustomEvents.h to Source folder: #pragma once #include "UltraEngine.h" namespace UltraEngine { //load a game map const EventId EVENT_GAME_START = EventId(1001); //load a main menu const EventId EVENT_MAIN_MENU = EventId(1002); } If you created a file manually then do Refresh in Solution Explorer. Remember to include a class files to a project via sub menu called with right click on file in Solution Explorer. Create MainMenu in Source folder. MainMenu.h: #pragma once #include "UltraEngine.h" using namespace UltraEngine; //Object is convenient class for a parent class due As() - casting, and Self() methods class MainMenu : public Object { protected: //constructor - you can think about it as a first method that will be called //protected in this case because we will use create() method for making a new Manu MainMenu(); //shared_ptr is smart pointer that will destroy object automatically once all pointer of this objects are out of scope //in perfect world you need to have maximum only one shared pointer to specific class instance/object as class member, because otherwise object may stay in memory when you don't expect it //for cases when you need pointer without keeping an object you can use std::weak_ptr and it's method .lock() to get a shared_ptr for specific code scope //2D camera for GUI shared_ptr<Camera> uiCamera; //Scene is map entities in first place and you need to keep as long as you need to keep map object shared_ptr<Scene> scene; void init(shared_ptr<Framebuffer> framebuffer); public: static std::shared_ptr<MainMenu> create(shared_ptr<Framebuffer> framebuffer); shared_ptr<Interface> ui; shared_ptr<World> world; }; MainMenu.cpp: #include "UltraEngine.h" #include "MainMenu.h" #include "CustomEvents.h" //default empty constructor MainMenu::MainMenu() = default; //it's better to always use shared_ptr and it's a static dedicated method to make one std::shared_ptr<MainMenu> MainMenu::create(shared_ptr<Framebuffer> framebuffer) { //struct are kinda mini classes, using it in create methods for proper accesses struct Struct : public MainMenu {}; auto instance = std::make_shared<Struct>(); instance->init(framebuffer); return instance; } static bool NewGameButtonCallback(const Event& ev, shared_ptr<Object> extra) { EmitEvent(EVENT_GAME_START, nullptr, 0, 0, 0, 0, 0, nullptr, "start.ultra"); return true; } static bool ExitButtonCallback(const Event& ev, shared_ptr<Object> extra) { //to close application exit(0); return true; } void MainMenu::init(shared_ptr<Framebuffer> framebuffer) { world = CreateWorld(); scene = LoadMap(world, "Maps/menu.ultra"); //Load a font auto font = LoadFont("Fonts/arial.ttf"); //Create user interface auto frameSize = framebuffer->GetSize(); ui = CreateInterface(world, font, frameSize); ui->SetRenderLayers(2); //to make backgrount transparent ui->root->SetColor(0.0f, 0.0f, 0.0f, 0.0f); //Create camera for GUI uiCamera = CreateCamera(world, PROJECTION_ORTHOGRAPHIC); uiCamera->SetPosition(float(frameSize.x) * 0.5f, float(frameSize.y) * 0.5f, 0); uiCamera->SetRenderLayers(2); //for correct rendering above 3D scene uiCamera->SetClearMode(CLEAR_DEPTH); //Menu buttons auto newGameButton = CreateButton("New game", frameSize.width / 2 - 100, 125, 200, 50, ui->root); ListenEvent(EVENT_WIDGETACTION, newGameButton, NewGameButtonCallback); auto exitButton = CreateButton("Exit", frameSize.width / 2 - 100, 200, 200, 50, ui->root); ListenEvent(EVENT_WIDGETACTION, exitButton, ExitButtonCallback); } Let's get back to main.cpp. We have files to include: #include "MainMenu.h" #include "CustomEvents.h" Also we need menu as global var: shared_ptr<MainMenu> menu; Add those fuctions above main one, we will need them for event system: static bool StartGameEventCallback(const Event& e, shared_ptr<Object> extra) { //nothing just for now return true; } static bool MainMenuEventCallback(const Event& e, shared_ptr<Object> extra) { menu = MainMenu::create(framebuffer); //switching current render and update targets for loop currentWorld = menu->world; currentUi = menu->ui; return true; } Put this above main loop: //to show Loading screen before Main Menu loadingWorld->Render(framebuffer); //ListenEvent are needed to do something in callback function when specific even from specfic source (or not, if 2nd param is nullptr) emitted ListenEvent(EVENT_GAME_START, nullptr, StartGameEventCallback); ListenEvent(EVENT_MAIN_MENU, nullptr, MainMenuEventCallback); //let's try it out! EmitEvent(EVENT_MAIN_MENU); Just in case if something one wrong, current main.cpp file main.cpp It's time to to take a look on our fresh menu! If you did not blink you could also see a Loading screen, at lest in debug mode. Unfortunately white screen before Loading screen can be noticed way easier and i don't know yet a way to fix it. We need to modify FPSPlayer component just a little bit. Add to its header FPSPlayer.h bool doResetMousePosition = true; And new condition for mouse position reset in FPSPlayer.cpp in Update() if (doResetMousePosition) { window->SetMousePosition(cx, cy); } One big thing left - a game to play. Add Game class to project: Game.h: #pragma once #include "UltraEngine.h" #include "Components/Player/FPSPlayer.h" using namespace UltraEngine; class Game : public Object { protected: shared_ptr<Camera> uiCamera; shared_ptr<Scene> scene; shared_ptr<FPSPlayer> player; shared_ptr<Widget> menuPanel; Game(); void init(shared_ptr<Framebuffer> framebuffer, WString mapPath); public: //to show/hide game menu on Esc static bool GameMenuButtonCallback(const Event& ev, shared_ptr<Object> extra); static std::shared_ptr<Game> create(shared_ptr<Framebuffer> framebuffer, WString mapPath); shared_ptr<Interface> ui; shared_ptr<World> world; }; Game.cpp: #include "UltraEngine.h" #include "Game.h" #include "CustomEvents.h" Game::Game() = default; std::shared_ptr<Game> Game::create(shared_ptr<Framebuffer> framebuffer, WString mapPath) { struct Struct : public Game {}; auto instance = std::make_shared<Struct>(); instance->init(framebuffer, mapPath); return instance; } bool Game::GameMenuButtonCallback(const Event& ev, shared_ptr<Object> extra) { if (KEY_ESCAPE == ev.data && extra) { auto game = extra->As<Game>(); bool isHidden = game->menuPanel->GetHidden(); game->menuPanel->SetHidden(!isHidden); //we can get a game window anywhere, but take in mind that it will return nullptr, if window is not active ;) auto window = ActiveWindow(); //checking just in case if we actually got a window if (window) { //hiding cursor when hiding a menu and vice versa window->SetCursor(isHidden ? CURSOR_DEFAULT : CURSOR_NONE); } if (game->player) {//to stop cursor reset to center when menu on game->player->doResetMousePosition = !isHidden; } } //If the callback function returns false no more callbacks will be executed and no event will be added to the event queue. return false; } static bool MainMenuButtonCallback(const Event& ev, shared_ptr<Object> extra) { EmitEvent(EVENT_MAIN_MENU); return true; } static bool ExitButtonCallback(const Event& ev, shared_ptr<Object> extra) { exit(0); return true; } void Game::init(shared_ptr<Framebuffer> framebuffer, WString mapPath) { world = CreateWorld(); scene = LoadMap(world, mapPath); for (auto const& entity : scene->entities) { auto foundPlayer = entity->GetComponent<FPSPlayer>(); if (foundPlayer) { player = foundPlayer; break; } } auto font = LoadFont("Fonts/arial.ttf"); //Create user interface for game menu auto frameSize = framebuffer->GetSize(); ui = CreateInterface(world, font, frameSize); ui->SetRenderLayers(2); ui->root->SetColor(0.0f, 0.0f, 0.0f, 0.0f); uiCamera = CreateCamera(world, PROJECTION_ORTHOGRAPHIC); uiCamera->SetPosition(float(frameSize.x) * 0.5f, float(frameSize.y) * 0.5f, 0); uiCamera->SetRenderLayers(2); uiCamera->SetClearMode(CLEAR_DEPTH); //widgets are stays without extra shared pointers because parent widet, ui->root in this case, keep them //to remove widget you should do widget->SetParent(nullptr) menuPanel = CreatePanel(frameSize.width / 2 - 150, frameSize.height / 2 - 125 / 2, 300, 250, ui->root); auto menuButton = CreateButton("Main menu", 50, 50, 200, 50, menuPanel); ListenEvent(EVENT_WIDGETACTION, menuButton, MainMenuButtonCallback); auto exitButton = CreateButton("Exit", 50, 150, 200, 50, menuPanel); ListenEvent(EVENT_WIDGETACTION, exitButton, ExitButtonCallback, nullptr); //we don't need game menu on screen while playing menuPanel->SetHidden(true); //and we will need it once hitting Esc button ListenEvent(EVENT_KEYUP, nullptr, GameMenuButtonCallback, Self()); //take in mind that extra param will be kept as shared_ptr in callback ^ } Add new Game include and global var to main.cpp: #include "Game.h" shared_ptr<Game> game; Update function callbacks: static bool StartGameEventCallback(const Event& e, shared_ptr<Object> extra) { //destroying a main menu menu.reset(); //to show loading screen loadingWorld->Render(framebuffer); game = Game::create(framebuffer, "Maps/" + e.text); //switching current render and update targets for loop currentWorld = game->world; currentUi = game->ui; //to avoid crash when engine will try to proccess prev ui, catching in main loop throw std::invalid_argument("Game"); return true; } bool MainMenuEventCallback(const Event& e, shared_ptr<Object> extra) { //destroying a game instance if one existed game.reset(); //to show loading screen loadingWorld->Render(framebuffer); menu = MainMenu::create(framebuffer); //switching current render and update targets for loop currentWorld = menu->world; currentUi = menu->ui; throw std::invalid_argument("Main menu"); return true; } Find EmitEvent(EVENT_MAIN_MENU) and wrap in try-catch: try { EmitEvent(EVENT_MAIN_MENU); } catch (const std::invalid_argument& e) { //do nothing } Same for ui processing: try { if (currentUi) { currentUi->ProcessEvent(ev); } } catch (const std::invalid_argument& e) { //Stop processing old ui } And in the end we have a game with own menu: All created and modified classes: FPS game with menu.zip Maps: Maps.zip Repository: https://github.com/Dreikblack/CppTutorialProject/tree/menu-loading-screen-and-gui
  5. I am going through the documentation and I may have ran into a bug or maybe have misunderstood the program. In the image viewer the colors are inverted, for example below the blue image is how it's supposed to be but when displayed in the "Create Image Viewer" program, it is red. When I "Save" the file it goes back to being blue like it should. I don't see anything in the code manipulating the color. Whats happening here?
  6. Just bought LW today. I'm going through tutorials and I'm trying to assign a script to an object (the fan tutorial). I click on an object and then I select my rotation script. Now if I try to run/debug the game, nothing happens. If I select a different object after assigning a script, and then select my fan again, then the script disappears. It's no longer assigned. https://www.leadwerks.com/learn?page=Tutorials_Lua-Scripting_Introduction-to-Lua I'm on Debian 10. Any ideas what I may be doing wrong?
  7. On http://www.leadwerks.com/werkspace/page/tutorials/_/editor-interface-r1 It says you will see the welcome page initially, but you don't. It also says you can enable/disable it under Help:Welcome Page, but that option doesn't exist.
  8. Hi Leadwerks community. Several people in the past few years suggested to start a modest kickstarter or make some sort of paid tutorial set available using educations sites like udemy.com. Previous attempts at tutorial projects didn't go so well, so a change is needed. Project Saturn Game from scratch Users seem to like this approach better In the end there were too many code changes/breaks in default scripts for me to continue this. OLED Lua basics and editor usage videos. Tried out patreon: at max 3 subscribers. So I stopped using it. Although the video quality and length were improved, the views were so low that I stopped spending time on it. Then there is also SplineTools. I see the same thing there, although it is not a tutorial but a paid script. Very little usage At the moment of writing, I haven't earned anything yet. I blame the Steam workshop partially for this. New attempt I really like to see more people using Leadwerks. So here is my idea for a new tutorial project. Feedback is more than welcome. Kickstarted project The endgoal for this project is to have a cool, complete tutorial project. The endgoal is not to make a huge amount of money. however I have spend a lot of personal time in previous projects. I would hate it to see my precious time go to waste because users do not watch or read the content. Target goal (price)? Honestly no idea. Again, I do not expect to earn a lot on this. I would probably earn more money delivering mail or flipping burgers. Game type: Tower defense FPS is the most used genre for Leadwerks games so I want to do something else. I require only few animations. Several Leadwerks GUI skills to be learned. Imagine clicking on a tower, display a UI object at that specific tower. Different tower types require different game mechanics that can be taught. The amount of towers is not important, the game mechanic is: Direct hit tower: good for demonstrating raycast. (similar to Saturn weapon tutorial) Bullet: simplest effect that can be achieved. Tesla: good way to demonstrate sprites/electricity Area hit tower: either in a cone or in a radius of the tower. AABB example Projectile tower: slow moving object, physics involved. Models/textures/Sound would be provided. I have a friend who can model really well, delivers consistent quality and has a 'friend' price. Progress of the project will be publicly visible in the new Leadwerks Projects forum Project will be opensourced using Github. Language? Lua will attract more users, is quicker to set up and can be used in the editor. This brings us also to the question if the editor should be used in the first place. The game could be procedural for instance. A good showcase for C++ would be a nice change too. Leadwerks version? We have the stable Leadwerks 4.5/4.6. Possibly new game template for Josh to use with Leadwerks 5. Leadwerks 5 is a long way of though. Plus the game would be written in C++ since Lua is not available yet. Development process Game is first made from scratch. When that is done and passes review, the tutorials are made. Written tutorials on how to make the entire game from scratch. From starting a new project, to importing assets, to writing the code and finishing the game. Depending on how much time everything takes, videos could be recorded as well.
  9. Hello Everyone! This is my first post and first question here! Hope you can help! I'm new to Leadwerks and somewhat to Game Dev. I'm currently enjoying learning Leadwerks, and I just reached the Marble Game tutorial. The only thing I'm facing is that as soon as I create a project with the Marble Game template, I'm getting the full playable game, while it is supposed to be non-playable to learn building it. Is there any available files for this tutorial? That would save me modifying the complete game to look like the tutorial one. Thanks in advance. Lagli
  10. Hey guys, Besides the YouTube videos from the Leadwerks Channel, anyone know of some good LUA tutorials for Leadwerks? Any help appreciated! Thanks
  11. On http://www.leadwerks.com/werkspace/page/tutorials/_/models-and-animation-r8 This part is very non-intuitive. It didn't show the entire model at first, and didn't auto-play. There are no buttons with Play icons or tooltips. Randomly pressing the two buttons to the left of the slider, I managed to get it to 'start' - but all it was doing was flashing different body parts on the screen really quick. It didn't appear that anything moved, just flashed.
  12. On http://www.leadwerks.com/werkspace/page/tutorials/_/asset-browser-r5 The folder didn't open. I expected Nautilus or similar to open to the specified directory.
  13. On this page: http://www.leadwerks.com/werkspace/page/tutorials/_/editor-interface-r1 It says: "You can switch from four to one viewports by selecting the View > Single Viewport menu item." That option doesn't exist It also says: "The option to switch between single and four viewports can also be activated with a shortcut: F12." That didn't do anything either
  14. There is a typo in the Models and animation tutorial. Under the Models and Materials heading, second sentence. " We can seein the model " should be We can see in the model.
  15. In the Scene Editor Tutorial, under the Properties Editor heading, it asks to select the "Brick cylinder brush" but there is no Brick cylinder brush in the scene. In the example image the Floor is selected and in the next image Box side 1 is selected. I'm surprised Malachi missed this one
  16. On http://www.leadwerks.com/werkspace/page/tutorials/_/workshop-r11 It shows installing the Crate and Barrel asset After following the workaround to subscribe to it inside Steam http://www.leadwerks.com/werkspace/topic/12741-workshopbrowse-does-nothing/ The Workshop:Manage AddOns did not reflect the new item until the Editor was closed and relaunched After that, it showed the new entry, but will not allow install Leadwerks.log and update.log are both 0 bytes... I looked through the other related tickets (http://www.leadwerks.com/werkspace/topic/12081-installing-dlc-instructions/page__hl__workshop) , and the fact that the Install button is not clickable seems to be my problem.
  17. Found some tutorials on subjects that seem to come up alot on the Leadwerks forums: Texturing and modular assets. http://www.philipk.net/tutorials.html The tutorials are simple but graphically impressive.
  18. Issue is similar to http://www.leadwerks.com/werkspace/topic/12657-saving-a-map-does-not-add-extension/ On http://www.leadwerks.com/werkspace/page/tutorials/_/prefabs-r33 That doesn't work. It saves the file, but does not show up in the Asset Browser. You have to manually add the pfb extension for it to appear in the Asset Browser.
  19. On http://www.leadwerks.com/werkspace/page/tutorials/_/prefabs-r33 There is no visible indication of the emitter (other than x/y/z control points) at this point. Maybe it's because of: Error: Failed to load material "Materials/Effects/default.mat" Error: Failed to load material "Materials/Icons/emitter.mat" (That was referenced in http://www.leadwerks.com/werkspace/topic/12722-emitter-has-missing-materials/) Still no visible indication of the emitter Now the screenshots match up. The previous two did not. This could be a side effect of that other bug (missing materials) and may go away once those changes are propagated to us.
  20. On: http://www.leadwerks.com/werkspace/page/tutorials/_/textures-r6 Nothing happens. It doesn't appear to register there was an attempt.
  21. On http://www.leadwerks.com/werkspace/page/tutorials/_/textures-r6 That is not the behaviour that I see. Using: [L]eft click [R]ight click [M]iddle click croll wheel [d]rag Ld: move (correct) LRd: move (side effect of above, I think) Rd: nothing (documented to zoom, but doesn't) Md: nothing Rs: nothing Ms: nothing s: nothing (this was what the rest of the app uses)
  22. On http://www.leadwerks.com/werkspace/page/tutorials/ In reference to http://www.leadwerks.com/werkspace/page/tutorials/_/particle-emitters-r10 The tutorial is incomplete.
  23. On http://www.leadwerks.com/werkspace/page/tutorials/_/particle-emitters-r10 When it creates the emitter, I see these errors: Error: Failed to load material "Materials/Effects/default.mat" Error: Failed to load material "Materials/Icons/emitter.mat"
  24. On http://www.leadwerks.com/werkspace/page/tutorials/_/models-and-animation-r8 This section of the tutorial is outdated. It assumes you currently have 'Crates', which you don't. You currently have 'Fan' and 'Firepit'. As such, this section instructions you to overwrite your current copy with a binary-different version. The name should either be distinct, or it should be non-conflicting assets.
  25. It wouldn't allow me to respond to this thread http://www.leadwerks.com/werkspace/topic/12652-floor-blocks-light/ You have to press Enter before you can adjust the placement.
×
×
  • Create New...