Jump to content
    1. Past hour
    2. Hi! Im still planning what resources to include. Imagine a total war-like game, turn-based empire builder on a earth map. It's around the year 2100 after some cathastrophy so empires are starting to form: you control one of these upcoming empires. Large regions (such as south-western europe) are what you control (similar to the map of the boardgame Risk). You contruct infrastructure ("buildings") and train armies/navies/aircrafts/nukes! Focus is on war and building up your regions. Resources: Funds - Used for most things like infrastructure and units. Also for upkeep Influense - Used to affect others, diplomacy etc (not sure about this one...) Research - Used to unlock stuff and boosts (like +20% agriculture, unlock battlemech, +2 happiness from markets etc) Funds will come from these sources: Taxes. Main source. Causes unhappiness in your regions. Income based on regional ratings: Mining (regional rating. Can be boosted with infrastructure). Agriculture (gives mostly pop growth but also some funds) Drilling (oil and gas is still important). Logging? Infrastructure like manufacturing plants, ports etc. Thoughts? Influense (political power) is used in some strategy games (like Stellaris, hearts of iron) but would it work in a nuclear post-apoc when there is not much interaction between empires? Or maybe more interaction would be good? (also makes trade a viable mechanics). Influense could also be skipped and simply use funds (e.g. for bribing other empires) How would you gain influense? Research is gained from population - but strongly boosted by infrastructure (labs etc).
    3. Fulcrum.013

      Check Collision in advance

      Ok. Imagine a shеet of paper that lies on desk and have a u and v axes on it. You can move a point over sheet changing a values of u and v. Now lift up a sheet to make a some angle betwin desk and table. It not change ability to move a point over sheet (it coords on basis drawn on sheet still same and have same operations set to move it over sheet), But coords of point in 3D space has changed. So 3D coord of object that placed on some surface depends from u,v coords that relative to basis of its surface (aka surface coords) and properties of surface determined by equation of surface. Really lifting list up you dont changing a coords of point respectively to surface, you chaning a orientation of plane respectively to space where its surface placed. And to find a 3D coords from u,v coords of some point of surface it required only to substitute u,v to parametrical equation of surface. So you can just move a object placed on plane over its plane and recalculate its 3D point for rendering that is much eaily than move it in 3D and then align it to plane. Now imagine you have 2 sheets of paper. One of it lies on desk but other lifted up by some angle and aligned to first sheet along some edge. Obviuosly that second sheet have a other plane equation than first. so to move poiint from first sheet to second you have to recalculate a resulting point from surface coords of first sheet to surface coords of second sheet. It can be eaily done for points of alligned edge becouse its have same 3D coords for both planes. So you can move your object until central point reach portal edge , then recalculate a u,v respecively to second sheet basis (that require to solve simple equations system) and continue to move object but along second sheet.
    4. Daniel Pacheco

      Rocky Knight

      Wow! and the game is running on Itch.io. What are your plans with this game?
    5. You don't need a two dimensional array here. You only need an (one-dimensional) array of dynamic_pfl, and you can access the structs with arr_dynamic_pf[0].x, arr_dynamic_pf[1].x and so on. The entire struct (all the fields) are one element of the array, so you have only one dimension (the level number)
    6. Today
    7. I'm a beginner in C, maybee I don't understand arrays in C because as Webdeveloper I used Languages like ASP, Python, PHP, Javascript and Actionscript it was easier. My Goal is a two-dimensional array. First dimension: should contain the current level of the game, second dimension: object structure. When I compile and execute it seems, the first dimension is used as a structure. C:\_dev>gcc struct_def.c -o struct_def.exe -lmingw32 C:\_dev>struct_def.exe result x = 420.000000 x = 0.000000 < instead of 1200.000000 C:\_dev> The Game is very small and I would like to hardcode all the level data. without having to load the levels dynamically and without malloc. I want to iterate the array and refresh all the positions and making collision checks etc. then iterate the array again to calculate wich object are inside the camera to draw. How can I use the array as I would like it? First dimension: Level, second dimension: all the struct data? thank's for helping 😊 C ISO C98 <code> #include <stdio.h> #include <stdlib.h> #include <stdbool.h> struct dynamic_pfl{ bool player; int type; int pause_time; int moving_dir; float mspeed; float hspeed; float vspeed; float x; float y; float friction; int width; int height; int state; }; int main(){ int level = 5; //max levels of the game struct dynamic_pfl arr_dynamic_pfl[level][20] = { {false,1,4,2,40,0,0,420,580,0,128,64,0}, {false,2,4,2,40,0,0,1200,580,0,128,64,0}, {false,1,4,2,40,0,0,111,580,0,128,64,0}, {false,2,4,2,40,0,0,2222,580,0,128,64,0}, {false,2,4,2,40,0,0,666,580,0,128,64,0} }; printf("result\n"); printf("x = %f\n",arr_dynamic_pfl[0][0].x); printf("x = %f",arr_dynamic_pfl[0][1].x); return 0; } </code>
    8. Jonty K.

      Jittering in game

      will check and report....tx btw
    9. Scott Browne

      Graphics and Art Style

      It's a castle garden so it was designed for whatever they use them for, meetings weddings etc. It would be designed by a gardener. I think I will bring some flowers back and just do a better job at making it look better. I'll work on that brick again.
    10. Mirko Rossetti

      Check Collision in advance

      Actually i doesn’t have any udea to how do it.
    11. The user reports that the release version of it works without sending any loose DLLs so this seems what I need to (and should) do Thank you all for the explanations!
    12. Gnollrunner

      Mountain Ranges

      For this entry we implemented the ubiquitous Ridged Multi-fractal function. It's not so interesting in and of itself, but it does highlight a few features that were included in our voxel engine. First as we mentioned, being a voxel engine, it supports full 3D geometry (caves, overhangs and so forth) and not just height-maps. However if we look at a typical world these features are the exception rather than the rule. It therefor makes sense to optimize the height-map portion of our terrain functions. This is especially true since our voxels are vertically aligned. This means that there will be many places where the same height calculation is repeated. Even if we look at a single voxel, nearly the same calculation is used for a lower corner and it's corresponding upper corner. The only difference been the subtraction from the voxel vertex position. ...... Enter the unit sphere! In our last entry we talked about explicit voxels, with edges and faces and vertexes. However all edges and faces are not created equal. Horizontal faces (in our case the triangular faces), and horizontal edges contain a special pointer that references their corresponding parts in a unit sphere, The unit sphere can be thought of as residing in the center of each planet. Like our world octree, it is formed from a subdivided icosahedron, only it is not extruded and is organized into a quadtree instead of an octree, being more 2D in nature. Vertexes in our unit sphere can be used to cache height-map function values to avoid repeated calculations. We also use our unit sphere to help the horizontal part of our voxel subdivision operation. By referencing the unit sphere we only have to multiply a unit sphere vertex by a height value to generate voxel vertex coordinates. Finally our unit-sphere is also used to provide coordinates during the ghost-walking process we talked about in our first entry. Without it, our ghost-walking would be more computationally expensive as it would have to calculate spherical coordinates on each iteration instead of just calculating heights, which are quite simple to calculate as they are all generated by simply averaging two other heights. Ownership of units sphere faces is a bit complex. Ostensibly they are owned by all voxel faces that reference them (and therefore add to their reference counter) . However this presents a bit of a problem as they are also used in ghost-walking which happens every LOD/re-chunking iteration, and it fact they may or may not end up being referenced by voxels faces, depending on whether mesh geometry is found. Even if no geometry is found we may want to keep them for the next ghost-walk search. To solve this problem, we implemented undead-objects. Unit sphere faces can become undead and can even be created that way if they are built by the ghost-walker. When they are undead they are kept in a special list which keeps them psudo-alive. They also have an un-dead life value associated with them. When they are touched by the ghost-walker that value is renewed. However if after a few iterations they are untouched, they become truly dead and are destroyed. Picture time again..... So here is our Ridged Multi-Fractal in wire frame. We'll flip it around to show our level transition........ Here's a place that needs a bit of work. The chunk level transitions are correct but they are probably a bit more complex than they need to be. We use a very general voxel tessellation algorithm since we have to handle various combinations of vertical and horizontal transitions. We will probably optimize this later, especially for the common cases but for now it serves it's purpose. Next up we are going to try to add threads. We plan to use a separate thread(s) for the LOD/re-chunk operations, and another one for the graphics .
    13. Stragen

      OOP is dead, long live OOP

      I'll be heading to PAX, will have to give the game a run... will see how polished your shaders look in person.
    14. Esteban5XG

      Begginer at writting for video games.

      Hi there! I'm new at this forum. Working on a new game, doing all the writing. It is my believe that writing is still important in the game procedure, not because of how much the gamer is gonna read about, but for the unconciouss listening. I mean, it is all the lore behind what makes a game richer. for example, in this new game I working on, the point where the gamer starts playing is completely far away from the point where I started the whole history. And that¡s because I really need to create a complete new atmosphere, with all the past character's, the origin indeed, in order to make everything have sense. Well, timeline is like the line I wanna show to the gamer but only the parts I think the player needs to know in the very moment he is playing. Obiously, if you are playing a chess game, for example, it is not necessary to write a complete story. But you do realize how important it's gonna be to enrich the game. Thanks for the thread, it's good to share opinions about this part of the game.
    15. Hello there! I'd like to show you my new game - Hurry Birdie. It's an endless game where you have to dodge tree brunches and stones falling from above. Your birdie flies from side to side and speeds up when you press the screen. Features: * Nice design; * You can unlock new birdies; * Easy to play; * Leaderboard; * Good timekiller. Download here: iOS: https://itunes.apple.com/app/id1434970622?mt=8 Android: https://play.google.com/store/apps/details?id=com.abdullakh.hurrybirdie
    16. Naturally it still have G acceleration but also it have a horisontal velocity that not affected by gravity and allow to reach downhill side of loop prior to fall down significantly. Overdue of gravity force works for cost of accomulated kynetic energy. So common simulation of Newton laws and collision response performed by any phisical engine complitely enought to simulate effect that you want.
    17. KevDev

      Texture Crafter

      Texture Crafter is a package that contains several textures that can be combined and edited to create new textures. Currently, the pack contains 5 base textures and a total of 13 secondary textures. The secondary textures work as a layer over the base ones. The textures are tileable and of course you can import your own custom textures into the editor so you can combine your custom textures with the textures from the pack. ► Get it at Unity Asset Store Roadmap: Possibility to add more different fields around the main one to check how it tiles with other textures. Possibility to generate automatically an autotile from a few textures of the same type of terrain. Contact: contact@keviniglesias.com www.keviniglesias.com
    18. The force you are looking for is the centripetal force. Here's an article that has the formula for the minimum speed needed to complete the loop, it may help: https://www.dummies.com/education/science/physics/calculate-the-velocity-necessary-to-counteract-gravity-in-a-loop/
    19. Miss

      Enum size

      I just ran into an issue with a function in C++ returning an enum with 1 byte in size (enum "inherits" from uint8_t). The function was registered as a thiscall. Angelscript seemed to assume it wasn't 1 byte in size, causing it to return an invalid value. I had to write a wrapper function work around this. Is there a way to specify size for enums? (This was on x86 on Angelscript 2.32.0 by the way.)
    20. glararan

      Device lost

      Ok so problem was in QVulkanWindow implementation of Qt framework. Because I was unable to activate debug callback I wrote my own implementation which works.
    21. LorenzoGatti

      Graphics and Art Style

      Regarding the purpose of this space, think about people: the old version shows a much higher time and money budget for gardening (those flowers don't grow themselves) while the revised version shows a rather lower effort (neat but plain). Whose courtyard is it? Who is the gardener? Design advice: Brick textures are still too repetitive the round table (?) in the middle is too large for its space, put more pavement around it (and compensate it with more grass around the walls, particularly in the corners by the flowering trees) The columns are extremely inappropriate. If you insist about them, they should end below the balcony; arches or pillars would probably look better.
    22. on any location in the Source Code like in my example?
    23. #include does exactly that - copies the source code out of the requested file and pastes it at that location.
    24. For standalone games, gamejolt.com or itch.io are great. I’ve been using gamejolt, and I highly recommend it.
    25. LorenzoGatti

      Improve Property System

      Post code to let us understand what you are talking about. To begin with, what it is that you are calling a "property" or a "setting", what the corresponding classes do (if they are slow, they are nontrivial), and what is "editor mode" .
    26. Which the compiler then composes? Like in PHP? #include <stdio.h> require `inc_struct_declarations.c`; require `inc_functions.c`; int main() { require `inc_var_declarations.c`; require `inc_keyb_events.c`; require `inc_game_logic.c`; require `inc_gfx_output.c`; return 0; }
    27. Maybe you should find a publisher. If your game is great they share with you their know-how for a percentage of revenue. Great Google strategy for visibility in long-term is very important too. I mean for keywords related to your game. For example "strategy online football game". Marketing and active community is key to success. Facebook Ads. Contest with prizes, Facebook Ads, collecting feedback - everything from this is expensive but without it will be very hard. I do not know how it works but I know that also good relations with Google Play and iOS Store are very important. I am sure that mobile game devs are positioning their games in stores. The hard topic at all.
    28. Hi everybody, Me, Xylvan, announces Xilvan Design are building 3D games. Since 1993, our kindly official gaming related pages. (please click on each links, download games & bookmark the pages): Soul of Sphere Platinum v4.37. Age of Dreams:Abyss of Atlantis v1.5. Lights of Dreams IV: Far Above the Clouds v9.27. Candy World II: Another Golden Bones v9.47. Candy Racing Cup: The Lillians Rallies v3.01. Candy World Adventures IV: The Mirages of Starfield v7.57. Candy to the Rescue IV: The Scepter of Thunders v7.17. Candy in Space III: A dog to the Space v5.47. Candy's Space Adventures: The Messages from the Lillians v17.47. Candy's Space Mysteries II: New Mission on the earth-likes Planets v7.47 New Xilvan Design Websites. Xilvan Design's Youtube Channel. Friendly, Alexandre L., Xilvan Design.
    29. Gnollrunner

      OOP is dead, long live OOP

      I think there is a difference between a bug, one for which the cause is understood and "unexplained behavior". I used that combination of words intentionally. IMHO leaving the latter in your code is asking for trouble. I've seen people bitten by this many times. If I don't understand why something is happening I go find out. I have even had occasions where I seemingly fixed something but didn't understand why my change had fixed the problem. In that case I will go put the bug back in and trace it until I understand why it occurred, and if my change really did fix it or if it simply masked some manifestation of the bug. I'm a firm believer in understanding your code as much as possible. I don't like to tell someone how to do their job, but on the other hand if they are asking for my help, I refuse to waste my time chasing a possible ghost. If someone can't fix their own code and need me to help them, then I'm in command. If they don't like it, they can find someone else to help them, however in reality I've never had any push-back on that as people tend to appreciate when you are spending your time helping them.
    30. Hodgman

      OOP is dead, long live OOP

      I'm getting my indie game ready to exhibit at PAX at the end of October, so any free would-be-blog-writing-time is probably going to get eaten up by shader-code-polishing instead until then
    31. frob

      FXML and CSS in JavaFX

      They are independent. FXML is a markup language used for JavaFX. Since you are trying to build a GUI in JavaFX you'll probably to use it. FXML describes what UI elements like labels and text boxes should appear on the screen, and where they belong. FXML allow you to change the layout without recompiling the code. You can design the application to manually place the elements in code if you prefer. You can define your dialog boxes and window layouts by hand although it is much faster using IDEs that have tools to let you position your UI elements easily using FXML files. CSS is a style tool for web pages. It is often abused in corporate environments because marketers and artists refuse to accept that CSS is often overridden by users and script blockers, and can be modified or completely ignored by web browsers and user. JavaFX allows you to include styles from CSS so that your application can have a visual style that matches your web pages. Mostly it was added to make marketers happy for consistent branding, and they are a thorn in the side of developers forced to use them.
    32. jbadams

      Free Images?

      Have you had a look at the "free art assets" topic pinned in this forum? It has links to some good options.
    33. Rutin

      How to start for newbie?

      I probably should've posted some good C# resources! My apologies! Thanks for posting the Unity link @babaliaris I learned C# simply off of references as I come from C++, but these are the resources I would strongly suggest looking into: C# Book: C# 7.0 in a Nutshell - http://shop.oreilly.com/product/0636920083634.do MSDN: https://docs.microsoft.com/en-us/dotnet/csharp/ https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/ https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/ https://docs.microsoft.com/en-us/dotnet/csharp/quick-starts/ I hope this helps!
    34. RidiculousName

      Free Images?

      Could someone point me to a website with free images I could legally use in a game? I would like to choose completely free-to-use images just in case I may want to earn money from the game somehow (very small chance, I know).
    35. Yesterday
    36. L. Spiro

      Creating a language - Static Libraries

      You do some work when creating the .EXE, as you have to build your import and export tables, but that is all done via your own custom routines if it is your own custom language and compiler. Once you have a .EXE your work is done. Windows will use the offset table to write the correct function addresses into the correct locations in your code (or commonly a simple array of function addresses will be updated) based off your import table. This is not your run-time task. There is no black magic on your side. L. Spiro
    37. babaliaris

      How to start for newbie?

      First of all you must know at least the basics of programming. Then your best option like @Rutin said, is to start with unity and c# . Unity is great and has amazing tutorials and support for you to learn. You just need to be a little familiar with object oriented programming and you are good to go! A very dissent video series for c#: The New Boston C# Series (Of course it's always better to buy a good book to read. Books are always better for learning). You can find some books here. To start learning with unity visit this page and you are good to go! Don't forget to navigate more on the unity web site, they have awesome stuff to teach you! I think this is the easiest way to start with game development.
    38. Iris_Technologies

      Creating a language - Static Libraries

      I thinked about the fact that adding a procedure to the import table of a .exe could be the answer. But i didn't think on it pretty well. So, you are telling me basically that, if i add the demangled function name and the base RVA, which i could extract from the .dll without needing to relocate, on the import table, when the .exe is loaded into memory, the RVA of the imported functions will be relocated by the OS loader and i don't need to do any black magic?
    39. Distance Fields explains an O(n) algorithm that calculates 2D distance fields by operating on rows and treating samples as overlapping quadratic parabolas shows ideas to visualize distance fields, generate tiling noise and some use-cases of distance field functions wayback-archive 2018 XDC - Khronos slides from XDC (X.Org Developer’s Conference) Vulkan timeline semaphores allow increasing a 64-bit value on signal and wait on “greater than” a target value unified system for CPU and GPU waits look at how to implement them in the drivers many more talks about OS-level graphic topics wayback-archive Mesh Shader - Implicit Subdivision on the GPU compute shader based adaptive GPU tessellation technique using Mesh Shaders on Turing up to ~25% rendering time reduction at high tesselation rates Introduction to Real-Time Ray Tracing with Vulkan explains the Vulkan ray-tracing extension contains an overview of the ray tracing pipeline, the new shader types and how to interact with the API shows how to generate the acceleration structure, update and compact it as required wayback-archive Deep Compositing and Reprojection explains the mathematical foundation behind deep composition that allows compositing of volumetric effects such as fog wayback-archive Rendering the Moana Island Scene Part 2: A production scene from a hobby renderer walkthrough of the steps required to render the Moana scene in the authors custom path tracer uses a binning scheme on rays combined with on-demand geometry loading to be able to render the scene on a 32 GB RAM machine wayback-archive Project: SDL render batching discusses a change to the SDL render back-end that will batch CPU rendering commands to reduce the number of draw calls required this will improve performance significantly wayback-archive Gfx-hal Tutorial part 2: Vertex buffers next part of the series on gfx-hal usage (low-level graphics API for Rust) adds support for loading and using vertex buffers wayback-archive Ripples For Days explains a water ripple system implementation that uses a top-down projection of ripples onto the water surface in a separate rendering pass wayback-archive distance functions updated SDF function for a capped cone, round cone, and an ellipsoid wayback-archive If you are enjoying the series and getting value from it, please consider supporting this blog. Support this blog Read more
    40. For longer-running games i recommend a new server/gameworld every five years. Regarding your question, i don't know exactlyhow the unlock-system works right now, but just locking items for purchase(and not usage) should fix the problem.
    41. Hello! I'm trying to understand how to load models with Assimp. Well learning how to use this library isn't that hard, the thing is how to use the data. From what I understand so far, each model consists of several meshes which you can render individually in order to get the final result (the model). Also from what assimp says: One mesh uses only a single material everywhere - if parts of the model use a different material, this part is moved to a separate mesh at the same node The only thing that confuses me is how to create the shader that will use these data to draw a mesh. Lets say I have all the information about a mesh like this: class Meshe { std::vector<Texture> diffuse_textures; std::vector<Texture> specular_textures; std::vector<Vertex> vertices; std::vector<unsigned int> indices; } And lets make the simplest shaders: Vertex Shader: #version 330 core layout(location = 0) in vec3 aPos; layout(location = 1) in vec3 aNormal; layout(location = 2) in vec2 aTexCoord; uniform vec3 model; uniform vec3 view; uniform vec3 projection; out vec2 TextureCoordinate; out vec3 Normals; void main() { gl_Position = projection * view * model * vec4(aPos, 1.0f); TextureCoordinate = aTexCoord Normals = normalize(mat3(transpose(inverse(model))) * aNormal); } Fragment Shader: #version 330 core out vec4 Output; in vec2 TextureCoordinate; in vec3 Normals; uniform sampler2D diffuse; uniform sampler2D specular; void main() { Output = texture(diffuse, TextureCoordinate); } Will this work? I mean, assimp says that each mesh has only one material that covers it, but that material how many diffuse and specular textures can it have? Does it makes sense for a material to have more than one diffuse or more that one specular textures? If each material has only two textures, one for the diffuse and one for the specular then its easy, i'm using the specular texture on the lighting calculations and the diffuse on the actual output. But what happens if the textures are more? How am i defining them on the fragment shader without knowing the actual number? Also how do i use them?
    42. Rutin

      How to start for newbie?

      If you're wanting to pickup 3D game development then a very good option would be learning C# and Unity.
    43. Welcome! You have a few options. You can either build on your Python with PyGame: https://www.pygame.org/news You can look into GameMaker Studio 2 which has drag and drop, but slowly get into their scripting language which is c styled 'GML': https://www.yoyogames.com/gamemaker Beyond that, there is always C# and Unity if you're up to it. I would suggest PyGame or GameMaker Studio 2 using GML. Once you get some 2D games done, look into Unity if you want to jump into 3D.
    44. Rutin

      What's a frog TODO?

      Looking forward to your progress!
    45. L. Spiro

      Creating a language - Static Libraries

      I don’t see the problem. If your binaries are meant to run on Windows (regardless of the language that compiled them) then you typically will end up with a standard .EXE which will be loaded and set to run like any other. This means you will necessarily be linking to the standard Windows libraries and the offsets will be fixed during run-time by Windows after loading your file. Even if you have some other plan and you don’t want to call the Windows provided GetProcAddress(), implementing it manually is fairly easy. Also note that the addresses of the most crucial Windows API functions are static across all executables of a platform (x86 or x64), so parsing just enough to get at those functions is even more trivial, but again I am not sure of the necessity. If you plan to run on Windows then you will make a .EXE file and all the work is done. L. Spiro
    46. alvaro

      Quaternions, how does ki = j?

      You still haven't given me the list of axioms you are starting with, and without that I can't even start to help you.
    47. Greetings fellow citizens of the underground, this is Subtyrannya, a dystopian merchant simulator with lovecraftian vibes, mystery and a whole lot of secrets for you to discover. You play as a lone merchant with his vehicle, driving trough the apocalyptic underground on the search for wealth, knowledge and one or two other things. Artist needed I am in need of a 2D - Artist who can produce isometric landscapes and locations or who can make basic portraits and sprites of objects. Almost all of the game will play out below ground, so expect to draw a lot of caves and rocks. Nativ english speaking Playtester needed As my Game is mostly described in text, I am in dire need of a english speaking playtester, that I can send all my documents to go trough once or twice to look for grammar, spelling and weird sentences. I am currently a month into developement and working on a short demo, which I update about every week. Feel free to take a look at it, on its itchio-page: https://korbohned.itch.io/subtyrannia If you are interested in making something for the fun of it, (Not sure if there will be anything sold in the end), feel free to hit me up. Just add me on discord: KorbohneD#9014
    48. supermikhail

      Help choosing an engine

      I actually got back into libGDX trying to follow challenge videos by a guy on Youtube, who was working in Processing. I'm not sure why. Maybe I was more afraid of learning new frameworks than now. Or I wanted to work in something more gamedev-oriented. The point is, I don't think I had many translation problems. Which is another argument for the position that it's not the platform but what you do with it.
    49. Greedy Goblin

      State Changes

      Games usually (if not always) require some way to manage state changes... and I'm sure most of you (if not all of you) know far more about State Machines than I do. And I'm certain that I could learn a heck of lot from reading up about the subject to build a state machine that works beautifully and makes my code look amazing etc etc. Pfft.. never mind all that... I'm building this game 'off the cuff' as it were, making it up as I go along and following the principle of 'I build what I need when I need it and only insofar that it adequately fulfils the requirements at that time'. I don't try to plan ahead (not in any granular sense anyway), I'm not building a reusable one-size-fits-all game engine, I'm not trying to make the code beautfiul, or win any awards or even make any money from the darn thing. It just needs to perform well enough for what I want it to do. So my immediate requirement is that I have a way to manage the player switching from walking to running to whatever. If I can use it elsewhere for other things then great... and I'll be honest, I do like reusable code so I tend to naturally sway toward that. What I'm trying to avoid is getting myself stuck in a rut, spending weeks/months deliberating over the smallest details because it's got to be 'perfect' and then realising I've still got 99.5% of the game to build! Quick and dirty is OK in my world. I often approach things from a top-down perspective. This boils down to: 'How do I want to instruct the computer to do x, y or z?' So for this particular requirement, how do I want to instruct the game that the player can change from walking to running and running to walking, or walking/running to falling (assuming I make that a player state - which I do), but not from sleeping to running for example? Hell, I don't even know all the states that I want yet, but these are the ones I have a feel for so far: Walking Running Skiiing Driving Falling Drowning Sleeping Eating Introducing 'When' I thought it might be nice to be able to write something like this in my player setup: // Configure valid player state transitions When( this.playerState ).changes().from( PLAYER_STATES.WALKING ).to( PLAYER_STATES.RUNNING ).then( function () { } ); When( this.playerState ).changes().from( PLAYER_STATES.RUNNING ).to( PLAYER_STATES.WALKING ).then( function () { } ); When( this.playerState ).changes().from( PLAYER_STATES.WALKING ).to( PLAYER_STATES.SKIING ).then( function () { } ); When( this.playerState ).changes().from( PLAYER_STATES.SKIING ).to( PLAYER_STATES.WALKING ).then( function () { } ); When( this.playerState ).changes().from( PLAYER_STATES.WALKING, PLAYER_STATES.RUNNING, PLAYER_STATES.SKIING ).to( PLAYER_STATES.FALLING ).then( function () { } ); There's probably a library for something like this out there, but heck, where's the fun in that?! So I create a new 'Stateful' object that represents a state (in this case the playerState) and it's allowed transitions and a 'When' function so I can write the code exactly as above: const Stateful = function () { } Stateful.isStateful = function ( obj ) { return obj.constructor && obj.constructor.name === Stateful.name; } Stateful.areEqual = function ( v1, v2 ) { return v1.equals ? v1.equals( v2 ) : v1 == v2; } Stateful.prototype = { constructor: Stateful, set: function ( v ) { let newState = typeof ( v ) === "function" ? new v() : v; for ( let i = 0; i < this.transitions.length; i++ ) { let transition = this.transitions[i]; if ( transition && typeof ( transition.callback ) === "function" ) { let fromMatch = Stateful.areEqual( transition.vFrom, this ); let toMatch = Stateful.areEqual( transition.vTo, newState ); if ( fromMatch && toMatch ) { // We can only change to the new state if a valid transition exists. this.previousState = Object.assign( Object.create( {} ), this ); Object.assign( this, newState ); transition.callback( this.previousState, this ); } } } }, transitions: Object.create( Object.assign( Array.prototype, { from: function ( vFrom ) { this.vFrom = typeof ( vFrom ) === "function" ? new vFrom() : vFrom; return this; }, to: function ( vTo ) { this.vTo = typeof ( vTo ) === "function" ? new vTo() : vTo; return this; }, remove: function ( fn ) { this.vFrom = this.vFrom === undefined ? { equals: function () { return true; } } : this.vFrom; this.vTo = this.vTo === undefined ? { equals: function () { return true; } } : this.vTo; for ( let i = 0; i < this.length; i++ ) { let transition = this[i]; let fromMatch = Stateful.areEqual( this.vFrom, transition.vFrom ); let toMatch = Stateful.areEqual( this.vTo, transition.vTo ); let fnMatch = fn === undefined ? true : transition.callback == fn; if ( fromMatch && toMatch & fnMatch ) { delete this[i]; } } } } ) ) } function When( statefulObj ) { if ( !Stateful.isStateful( statefulObj ) ) { throw "Argument must be a Stateful object"; } return { changes: function () { return { from: function ( ...vFrom ) { this.vFrom = vFrom; return this; }, to: function ( ...vTo ) { this.vTo = vTo; return this; }, then: function ( fn ) { if ( typeof ( fn ) === "function" ) { this.vFrom = this.vFrom === undefined ? [true] : this.vFrom; this.vTo = this.vTo === undefined ? [true] : this.vTo; for ( let i = 0; i < this.vFrom.length; i++ ) { for ( let j = 0; j < this.vTo.length; j++ ) { statefulObj.transitions.push( { vFrom: typeof ( this.vFrom[i] ) === "function" ? new this.vFrom[i]() : this.vFrom[i], vTo: typeof ( this.vTo[j] ) === "function" ? new this.vTo[j]() : this.vTo[j], callback: fn } ); } } } else { throw "Supplied argument must be a function"; } } }; } } } I drop the aforementioned 'When' statements into my Player setup and remove the old 'If' statements that were previously controlling changes between walking and running and insert the new playerState.set() calls where appropriate. e.g. "run": ( pc, keyup ) => { if ( keyup ) { _this.player.playerState.set( PLAYER_STATES.WALKING ); } else { _this.player.playerState.set( PLAYER_STATES.RUNNING ); } } And it seems to work! (Yes I was actually surprised by that) 😂 TheBerg-StateChanges.mp4 p.s. I've switched to using Bandicam for screen capture as it seems far superior to what I was using previously.
  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!