Jump to content

reepblue

Developers
  • Posts

    2,490
  • Joined

  • Last visited

Everything posted by reepblue

  1. If you were to modify an entity's friction, close the editor/open a new map, then reload the previous map, the entity's value will be reset. Also, the effect has no effect in-game so the widgets are lying.
  2. Ok, thought it was just the string rounding.
  3. I personally don't think a 1.0 release can't exist without proper grid snapping. I found level editing frustrating with the model's origin not snapping to the grid. This was way better in Leadwerks. Also, not being able to see the origin point is also unhelpful. If we can just get a sphere drawn at the model's origin when it's selected, that would be great.
  4. If Josh is ok with it, it would be cool if someone can port the code into this code base. I'm not sure I should be the one that should be doing this. My networking experience is nil and I don't have a good way of testing this.
  5. When resizing the grid in the editor, I notice that the reported grid sizes go by the following. 5.0mm 1.0 2.0 4.0 8.0 16.0 32.0 64.0 1.3 2.6 5.1 10.2 I dunno if this is just visual but I've ran into an issue with brushes no longer being on the grid when making geometry and I'm under the impression this is the cause. While I'm here, placing models doesn't feel right like it was in Leadwerks. I'm having issues placing models exactly where I want them. This seems to be the issue of the drag and drop system. To guarantee the model is on the grid, I have to set the position to 0,0,0 and then everything seems to work as intended. I should point out that most of my trouble is working with the 2D grid viewports.
  6. Was the fix pushed out yet, or no? I'm still getting the crash.
  7. This will be fixed in the next update. The console will no longer pause the game. It will instead change the Action Set to null before storing the previous set. Then it'll reapply the last Action Set when it's closed. I tried making it swap Action Sets based on what window was selected but I got weird results. I think it's time to make an in-game one and only have this as a fallback. You'll now be able to set mouse cursor types to an Action Set. It'll tell the application to swap cursors when SetActionSet() is called. If one isn't set, the default cursor will be used. controller->SetActionSetCursor("InGameControls", CURSOR_NONE); The only thing that'll pause your game is if you press the assigned Pause action key. Not even Terminate will pause the game.
  8. Sometime in the near future, I would like to give materials custom tags like I can for entities. This way I can mark a material to a surface type (concrete, metal, plastic, etc) , where it's intended to be used (space ship, shopping mall, etc) or any flags I want to apply to it (eg nocyclone). Then sometime later, I wish to search materials via tags.
  9. I can't seem to manipulate brushes using the face tool as I could in previous builds. Not a huge deal for how I do things, but I thought you should know.
  10. This is now an Ultra App Kit project. I've been using this all day today and it seems to be doing what it's supposed to do without any issues.
  11. I'm getting a Seek error with my game system, but this code should reproduce it with the map file below. #include "UltraEngine.h" using namespace UltraEngine; int main(int argc, const char* argv[]) { //Get the displays auto displays = GetDisplays(); //Create a window auto window = CreateWindow("Ultra Engine", 0, 0, 1280, 720, displays[0], WINDOW_CENTER | WINDOW_TITLEBAR); //Create a world auto world = CreateWorld(); //Create a framebuffer auto framebuffer = CreateFramebuffer(window); //Load scene auto scene = LoadMap(world, "Maps/saveloadparent.ultra"); //Main loop while (window->Closed() == false and window->KeyDown(KEY_ESCAPE) == false) { if (window->KeyHit(KEY_F5)) { //Save the starting scene to a file scene->Save("game.sav"); } //Reload the starting scene when space key is pressed if (window->KeyHit(KEY_F6)) { scene->Reload("game.sav"); } world->Update(); world->Render(framebuffer); } return 0; } saveloadparent.zip
  12. I've been watching a few tutorials from other engine and the trend is that people like to visually construct things. Right now, to make a first-person player one would. Create a Pivot in the scene. Attach the FPSController component. Now, this is all well and good, but things can be complicated for the non-programmer type. I'm experimenting with an approach that the user "builds" their player out of multiple components. Place a Pivot or Model for the player. Create a camera and parent it to the player entity having the end user set the height of the camera in the editor. Attach a FPSController component that ONLY handles controller movement and gets the camera reference via GetChild(). End user can attach multiple components to the camera such as custom look controls, HUD, etc. User would ideally save this as a prefab, but this isn't in the current build of the editor yet. I've already created two components with this approach, and I can already tell you it's so much easier to segregate functionality.
  13. Might as well get this started now although it's not going to be useful for a while. Github I mostly copied and pasted code from Cyclone. All it supports right now. is the overlay, stats and achievements. I used my own class with achievements for Cyclone because the one in the Leadwerks API held up the achievement notification until the application was closed. To be honest, the overlay and achievements is what most people want anyway. The Steamworks API can be a chore to work with. I hope to streamline this in the future.
  14. Pushed out an update. Settings.bat has $PROJECTNAME token so the template system will swap it with the name of the project (untested) Both Debug and Release builds are Windowed applications to have a cleaner appearance launching from the editor. Replaced CallCMDWindow() function with what @klepto2 posted above. (Launch the app with -cmd to make the console window.) Prevented empty strings being sent through the console event. Terminate() now asks if you really mean to force close the application. Sorta annoying but it feels much cleaner. Now you know if your game closes without asking, it's decently a crash. (To close the game without a confirmation, just emit EVENT_QUIT. Terminate is only used to get you out of a sticky situation.) Added a note about UAC and the Component Preprocessor. This is kind of tricky to do since we need to store the previous pause state and I'm not sure where to store it. The softlock is due to the stock Components not being setup to unpause the game. Must be the component/engine. The system just calls World::Save()/World::Load() functions. In due time. This went from being something you dropped in your existing project to a full template. I decided to go this route because adding all the files was tedious, and it helps prevent any conflicts Josh may want to push out. Just set up a UAK project. I had to change a few things so I'm gonna battle test it before releasing it. But yes, went from 20MB to 744KB!
  15. Ok, makes sense. Sometimes the most convenient setups aren't the most secure.
  16. My guess is that Windows is blocking the direct execution because it's a foreign app. Manually run the application tell UAC to trust the app. Or build try building the Preprocessor from the GitHub and use your version. Ether way, I didn't factor that into account. 🫢
  17. It's now easier to get started! The system is installable as a project template and component registration is much more streamlined.
  18. A few changes: This is now installable as a Template. Copy the "C++ Game" into the engine's Template folder and create a new project off of that. I didn't redistribute any SDK files so right now the start.ultra map will not work unless you were to copy over the stock components yourself. Removed start.ultra from the config's start map to prevent said issues. Visual Studio project is now included with all files added. My Component Preprocesor is now being used to make the component registration much more seamless. The app icon is now orange. Fixed any issues causing build errors. Some things I'm considering: Create a new start.ultra map to override the stock one. Ship my own components making use of the rest of the system. I've got more developer textures. I was going to ship it in its own package. I'm not sure including it would more help or bother people. Editing the template solution is really annoying. I might revive my premake setup. This will really help when Ultra Engine goes multiplatform.
  19. If you were to have an entity with a component attached to it and in the flowgraph, deleting the component from the entity doesn't reflect on the flowgraph. I know this is a heavy WIP, but thought I should bring it up.
  20. This simple application will scan your Components directory and create a function that'll register all your components in the engine. Use this in your Pre-Build event and then call the RegisterComponents() on top of your main entry. I didn't battle test this yet, but it seems to work. You are free to fork it, improve it, etc via GitHub. You can download the exe here.
  21. One of the things I don't like is that you need to cut the full line of text by spaces every time. The system I had for Cyclone only had the arguments available in a vector. This is a limitation of the Event System, but having it event based makes commands less static and it's way easier to do component based commands. One thing I still don't like thats in both systems is you need to do size checks on the argument vector before using it to prevent crashing. Other than that, it's a canvas for the programmer to do whatever they need done.
  22. Although cxxopts looks interesting, I wanted to stay exclusive to the engine's API for this. I didn't want to do anything that could/would change the workflow of how things are normally done with the engine. I might consider separating the logs by type though, I already have it sorted by colors at this point.
  23. Back in July, I set out to create a base for creating a version of Cyclone with Ultra Engine. I've gotten a lot of feedback from the release and started to conceptualize ideas on how to prevent or limit on making the same mistakes. One major goal I had was to compartmentalize the system. This should just exist on it's own and game code should just lay on top of this. This was possible thanks to the event system which cuts down on the number of pointers that need to be passed. Components can just listen to events from the program and act accordingly. Lastly, I've made the decision to open source this on GitHub as this is the kind of thing that users think about when it's too late. People just want to work on their cool games and not worry about the window or if a setting will be applied correctly. So here are 6 reasons/features of the Ultra Game System! 1. Window Management One of the top complaints I got with Cyclone is that users could not resize the window in-game. This was an engine limitation of Leadwerks This is now possible in Ultra Engine but it needs some elbow grease to make it work. The Game System does this for you. All you need to do is call GetProgram()->ResizeApp() and the graphics window class will recreate the window and framebuffer for you. By default, pressing F11 will swap between windowed mode and full screen. 2. Out-Of-Game Settings The Game System has an isolated window application for changing settings. The idea behind this is so there's a way to modify any window or graphics setting if an in-game one is unavailable. You probably shouldn't ship with just this solution as many people prefer to edit any setting within the game itself. This is accessible by using the -settings flag with the program. 3. Action Based Input System Years of research into this paid off when the Input Update for Cyclone released. The knowledge was carried over for the Game System. Only this time it's more dynamic! Simply set the controls in your main.cpp file: // Define default controls. static void InstallControls(shared_ptr<GameController> controller) { if (controller == NULL) return; // Program actions controller->SetAction("Pause", BUTTON_KEY_ESCAPE); controller->SetAction("Terminate", BUTTON_KEY_END); controller->SetAction("ConsoleApp", BUTTON_KEY_F1); controller->SetAction("Fullscreen", BUTTON_KEY_F11); controller->SetAction("Screenshot", BUTTON_KEY_F2); controller->SetAction("Quick Save", BUTTON_KEY_F5); controller->SetAction("Quick Load", BUTTON_KEY_F6); // Camera ButtonAxis moveaxis = { BUTTON_KEY_W, BUTTON_KEY_S, BUTTON_KEY_A, BUTTON_KEY_D }; controller->SetAction("Movement", moveaxis, "InGameControls"); controller->SetAction("Camera", AXIS_MOUSE, "InGameControls"); controller->SetAction("Sprint", BUTTON_KEY_SHIFT, "InGameControls"); controller->SetAction("Crouch", BUTTON_KEY_CONTROL, "InGameControls"); controller->SetAction("Climb", BUTTON_KEY_Q, "InGameControls"); controller->SetAction("Desent", BUTTON_KEY_E, "InGameControls"); controller->SetAction("Jump", BUTTON_KEY_SPACE, "InGameControls"); // Settings controller->SetSetting("Raw Mouse", false); controller->SetSetting("Inverse Mouse", false); controller->SetSetting("Mouse Smoothing", 0.0f); controller->SetSetting("Mouse Look Speed", 1.0f); } Then deriving your components off of the GameObject class, you can use GetInput() for input functionality. virtual void UpdateInput() { // Movement if (allowmovement) { float speed = movespeed / 60.0f; if (GetInput()->Down("Sprint")) { speed *= 10.0f; } else if (GetInput()->Down("Crouch")) { speed *= 0.25f; } if (GetInput()->Down("Climb")) GetEntity()->Translate(0, speed, 0); if (GetInput()->Down("Desent")) GetEntity()->Translate(0, -speed, 0); auto axis = GetInput()->Axis("Movement"); GetEntity()->Move(axis.x * speed, 0, axis.y * speed); } } Best part is the "Controls" tab will reflect whatever you have defined! 4. User Input via Console Having a developer console is essential for developing any game! The Game System has a very simple but flexible console that doesn't need any commands registered beforehand. To define a new command, just poll the EVENT_CONSOLEEXECUTE id in your component's ProcessEvent function. virtual void Start() { Listen(EVENT_CONSOLEEXECUTE, GetProgram()); } virtual bool ProcessEvent(const Event& e) { if (e.id == EVENT_CONSOLEEXECUTE) { auto line = e.text.Split(" "); auto cmd = line[0].ToString(); if (line.size() > 1 && !line[1].empty()) { if (cmd == "crosshair") { bool hide = (bool)line[1].ToInt(); hudcamera->SetHidden(!hide); Print(QuoteString(cmd) + " has been set to: " + line[1]); } } } } 5. Sound Managment A layer of functionality in the Game System allows for cleaner sound origination and playback. You can store sound variables (files, volume, pitch, range, etc) within a JSON script. { "audioProfile": { "file": "Sound/radio_dreamlandloop_mono.wav", "volume": 0.5, "range": 35.0, "loop": true } } Then load the file with the GameSpeaker class. auto file = "Sound/Profiles/Radio.json"; shared_ptr<GameSpeaker> speaker = CreateGameSpeaker(file, GetEntity()->GetPosition()); The GameSpeaker has Save/Load functions so the speaker's time and state can be restored. Here's an example of creating and restoring a GameSpeaker. virtual bool Load(table& properties, shared_ptr<Stream> binstream, shared_ptr<Map> scene, const LoadFlags flags) { Print("Loading component " + QuoteWString(name)); if (speaker) { if (!properties["componentspeaker"].is_null()) speaker->Load(properties["componentspeaker"], binstream, scene, flags); } else { auto file = "Sound/Profiles/Radio.json"; speaker = CreateGameSpeaker(file, GetEntity()->GetPosition()); if (!properties["componentspeaker"].is_null()) speaker->Load(properties["componentspeaker"], binstream, scene, flags); } return true; } virtual bool Save(table& properties, shared_ptr<Stream> binstream, shared_ptr<Map> scene, const SaveFlags flags) { properties["componentspeaker"] = {}; if (speaker) speaker->Save(properties["componentspeaker"], binstream, scene, flags); return true; } As of right now, the sound system doesn't support audio filters as I feel that the filter should be applied within a volume (or to the listener) and not the sound/speaker itself. I'm still thinking about how that should work. 6. Better Render Layer Managment Intergrated today, The Canvas class is a great way to ensure that there is one camera per render layer. I ran into an issue where a component would draw 2D graphics to the framebuffer, but when there were multiple instances of them, multiple cameras were being made and drawing over each other. Using GetCanvas() can prevent this from happening. auto canvas = GetCanvas(world, RENDERLAYER_HUD); auto sprite = CreateSprite(world, 1.0f, 1.0f); sprite->SetPosition((float)sz.x / 2, (float)sz.y / 2); RenderToCanvas(sprite, canvas); The Game System will be my main focus until the Ultra Engine version of Cyclone starts development which will use this as a foundation. I'll also be working on other small things to share so be on the lookout for those!
  24. Move the camera to the bottom edge of the framebuffer. 0,0 should be the top left of the screen. Then you can use the size of the framebuffer to position the sprite wherever you want like if you were using the Interface class. local size = framebuffer:GetSize() cam2:SetPosition(size.x * 0.5, size.y * 0.5f)
×
×
  • Create New...