Leaderboard


Popular Content

Showing content with the highest reputation since 11/14/17 in all areas

  1. 9 points
    Missile Command Challenge To celebrate the end of 2017 and beginning of 2018 we are making this a 2-month challenge. We also hope this gives late entrants enough time to submit entries. Your challenge is to create a single player Missile Command clone. Create an exact replica or add your own modifications and improvements! From Wikipedia: Play the original Missile Command on IGN at http://my.ign.com/atari/missile-command. Game Requirements The game must have: Start screen Key to return to the start screen Score system Graphics representative and capturing the spirit of a Missile Command clone Sound effects While single player is the goal, a multiplayer mode is also acceptable Gameplay mechanics in the spirit of Missile Command - the game does not need to be an exact clone, but it does need to have Missile Command gameplay Art Requirements The game may be in 2D or 3D Duration December 1, 2017 to January 31, 2018 Submission Post your entries on this thread: Link to the executable (specify the platform) Screenshots: Create a GameDev.net Gallery Album for your Project and upload your screenshots there! Post the link in the thread and your screenshots will be automatically linked and embedded into the post. Same with YouTube or Vimeo trailers. A small post-mortem in a GameDev.net Blog, with a link posted in this thread, is encouraged, where you can share what went right, what went wrong, or just share a nifty trick Source-code link is encouraged for educational purposes Award Developers who complete the challenge in the specified time frame will receive the 2018 New Year Challenge: Missile Command medal, which will be visible in their profiles. We are working on a new system on GameDev.net where you can submit your entries. It will be made public before this Challenge is complete. Details on how to submit them will be posted here when it is available.
  2. 7 points
    You've gotten some excellent answers, so let me take a different tack. At the end of the day, it's all about goals. Is your goal to: Develop the game of your dreams and bring your ideas to life? Go professionally into game design or high level programming (AI, game logic, etc)? Use an engine. This is what they are there for. Understand how everything works, and maybe eventually become a professional engine or low level developer? Build everything yourself. Obviously both are legitimate paths to choose, but they're very different.
  3. 7 points
    What people "normally do" depends on a lot of things. If you want a better answer you should ask a better question. Building your own engine Pros you have full control over what it does and how it does it you learn more about how engines work and how they're built, maintained, etc it's more challenging, and that's more fun for certain people you can make changes faster you own the IP Cons takes a larger time commitment limits the scope and quality of what you can accomplish on your own harder to find people to collaborate with who are familiar with the tech Using a third party engine Pros you can build a game faster you need less expertise to get started easier to find people to collaborate who are already familiar with the engine, editor, and data pipeline you get more and better features "out of the box" you could get access to ready-made assets through an asset store, or through the community it's less challenging, and that's more fun for certain people Cons you learn less because a lot of stuff is done for you and hidden behind the scenes you will likely have to pay licensing fees or percentages of profits you're at the mercy of whoever makes that engine supporting new features might take longer than if you're using your own tech making changes to the engine is harder than if it's your own tech in some cases making large, system-wide changes will be impossible a lot of it will be a "black box" that you dont know how it works if you realize towards the end of your project that there's a major issue (i.e. performance, etc) then you might be screwed because you're committed to this engine already. Rewriting everything with a new engine, or writing your own, at that point might not be a possibility
  4. 6 points
    http://www.tinker-entertainment.com/sitavriend/psychology-and-games/why-i-hate-fun/ Ever since I decided to specialize in game design I struggled with the word “fun”. It might sound silly to struggle with a term that is so central to the art of making games but it makes sense once you start to research ‘fun’. First of all very limited research has been done and secondly the term ‘fun’ is ambiguous. Fun means something different for everyone. Many other industries envy the games industry for making fun products. They mistakenly think that games are this magical medium that are automatically fun and engaging. As a result, they applied typical game elements such as XP and competition to apps as an attempt to make ‘boring’ tasks more fun. But game designers also struggle to make their games engaging and fun. Not every player enjoys playing every game or genre. I typically don’t enjoy most first person shooters because I suck at them. On the other hand it is not just games that can be fun. Many people think knitting is fun, others think watching a football match is fun or playing a musical instrument. What is considered fun often depends on someone’s expectations and their current context. A player has to be in the right state of mind before considering to play a game, they need to ‘want’ to play the game or do any other activity. This can be fun too. A researcher who attempts to understand fun more thoroughly is Lazzaro (2009). She formed the Four Fun Key model to distinguish between four different types of fun: Hard fun, easy fun, serious fun and people fun. Hard fun is very typical for many hardcore games and is fun that arises from overcoming challenges and obstacles. A key emotion in hard fun is frustration followed by victory. Easy fun can be achieved by engagement through novelty and can be found in many exploration and puzzle games. Emotions that are key to easy fun are curiosity, wonder and surprise. Serious fun is fun people have when they feel better about themselves or being better at something that matters. People fun is concerned with the enjoyment that arises from the interaction between people. You can think about competitive or cooperative games people play because they enjoy playing together rather than the game itself. The Cambridge dictionary defines fun as pleasure, enjoyment, entertainment, or as an activity or behaviour that isn’t serious (http://dictionary.cambridge.org/dictionary/english/fun). While we can measure pleasure and enjoyment objectively by measuring physiological changes in the body, we cannot always say we are having fun when we are enjoying ourselves. Besides that, within casual games mainly, pleasure and enjoyment are supposed to be “easy”. This means that you should be careful with challenging the player. If a player wins (often) they will have fun which is the complete opposite of many hardcore games. Within game design we often use flow theory interchangeably with fun. According to Csikszentmihalyi (1996), flow is a mental state in which a person in fully immersed in an activity. The state of flow can be achieved by matching the most optimal skill with the most optimal difficulty for a person. In the case of games, a player becomes so immersed that they forget about their surroundings and lose track of time. A learning curve is used in most games, both casual and hardcore, to account for player’s changing skill and difficulty level. However flow theory isn’t a definition for fun but can result in a player having fun. This mainly works for hard fun as easy fun doesn’t require the player to be fully immersed. References Lazzaro, N. (2009). Why we play: affect and the fun of games. Human-computer interaction: Designing for diverse users and domains, 155. Csikszentmihalyi, M. (1996). Flow and the psychology of discovery and invention. New York: Harper Collins.
  5. 6 points
    Why can't it be? What are you basing that on? It sounds like you're just repeating things that you've heard rather than basing this on development experience? It's currently lagging because they don't have a dedicated server, so you're relying on other players on vastly different connections to share game-state instead of having a single reliable connection to a data centre. If 100 players all simultaneously fire a 600RPM rifle at a target that's 3km away, then after three seconds there will be 3000 projectiles in the air. If the server ticks at 20Hz it needs a ray-tracer capable of 60K rays/s, which isn't much - it would only consume a tiny fraction of the server's CPU budget. If every bullet needs to be seen by every client (e.g. To draw tracers) then this would cause a burst of about 72kbit/s in bandwidth, which is fine for anyone on DSL, and a 7mbit/s burst on the server, which is fine for a machine in a gigabit data centre. None of this impacts latency because that's not how that works... And if not every bullet has visible tracers then these numbers go down drastically. [edit] I quickly googled and apparently PUBG does already run on dedicated servers in data centres? Maybe they still do client side hit detection for some reason though...
  6. 5 points
    For The Order our compositing system was totally based on parameter blending, much in the same spirit as Disney's material system that was presented at SIGGRAPH 2012. The only exception was when compositing cloth-based materials, in which case we would evaluate lighting with both our cloth BRDF as well as with GGX specular and then perform a simple linear blend of the two results. As far as I know UE4 is generally doing parameter blending as well, but I've never worked with that engine so I'm not very familiar with the specifics. As you've already figured out, you can't really simulate true multi-layer materials with parameter blending alone. To do it "for real", you have to make some attempt at modeling the light transport through the various translucent layers (much like they do in that COD presentation). This generally requires some approximation of volume rendering so that you can compute the amount of light absorbed as it travels through the medium. For something like car paint, at the minimum you'll need to compute your specular twice: one for the light being reflected off of the clear coat layer, and another time for the light being reflected off of the actual metallic paint flecks. I'd probably start out with something like this: Compute the specular reflection off of the clear coat using the roughness and IOR (F0 specular intensity) Compute the amount of light transmitted (refracted) into the clear coat using fresnel equations and IOR Compute the intensity and direction of the view direction as it refracts into the clear cloat using fresnel equations and IOR Compute the specular reflection off of the metallic layer using separate roughness and IOR (and perhaps a separate normal map), and also using the refracted view direction Final result is ClearCoatSpecular + MetallicSpecular * LightTransmitAmt * ViewTransmitAmt This would not account for absorption in the clear coat, but it would give you the characteristic dual specular lobes. If you wanted to account for absorption, you could compute a travel distance through the clear coat by having a "thickness" parameter and computing the intersection of the light/view ray with an imaginary surface located parallel to the outer surface. Using that distance you could evaluate the Beer-Lambert equations and use the result to modulate your transmittance values.
  7. 5 points
    Each of us have our own giants to face. This is a story about one of my giants. Something I never imagined could make a grown man cry, until it did. A 3D camera. No one can face your giants for you. This is a story, not a walkthrough. Expect no useful information. For that I recommend 50 Game Camera Mistakes by thatgamecompany's John Nesky. His job title is literally "camera designer". The story starts in 2014 with a seemingly harmless seven-day game jam. 7DFPS 2014 Exhausted from crunching on my first game, I decide it would be good to take a break and make a first-person shooter for 7DFPS. This is a terrible decision. The idea is simple: an FPS where you are the bullet. Click to jump from wall to wall. If someone's head happens to be between you and the next wall, sucks for them. The main problem is that, when you shoot to a new surface, the game necessarily buries your face directly into that surface, filling the whole screen with a solid blue color. You can see my first solution above. After landing, the game "reflects" your direction off the surface you landed on, and tweens the camera to face the new direction. So when you shoot into a wall head-on, the camera does a complete 180. Of course, I can't place the camera directly on the surface, or there would be clipping artifacts. So I space the camera a bit out from the wall, which leads to another problem: Here the extra space between the camera and the surface allows you to aim at any location on the surface and launch there. In theory, your "character" is actually flush with the surface, which should make this physically impossible. I throw a band-aid on this problem by clamping the camera so that it can't aim at or behind the surface it's attached to. I end up working 96 hours in a week to finish this masterpiece that will surely take the world by storm. Two YouTubers play it for a grand total of 10,000 views. Like every good vacation, the experience leaves me exhausted and depressed on Monday morning. Over the next 8 months, I finish my other game, take an actual vacation, then, instead of throwing away the Unity prototype like any sane person would, I start rebuilding it in a brand new custom C++ engine. The new game is an expansion of the prototype, which means more features, more gameplay, more pain and suffering! One of the first new features is the ability to crawl along walls, floors, and ceilings: A couple months later, camera problems start to manifest. As players crawl around different surfaces, I have to forcefully nudge the camera to keep it from staring straight into a wall. I use spherical linear interpolation (slerp) to smooth out the transition between angled surfaces, but it's still not great. In the gif below, the player on the right does not manually move their camera at all; the wall forces them to look up automatically. At this point, everything is completely unreadable and confusing. The first-person view prevents players from seeing their character, and they often take several minutes to realize they're playing as a creepy crawly spider bot. Once they finally get it, they can't figure out why the camera keeps getting forced around, and why they can't aim at the surface they're attached to. I slap on another band-aid in the form of a shader that blacks out everything "behind" you, everything that's physically impossible to reach. I also have it darken out of range areas. Now the game is not only unreadable and confusing, but also ugly! By sheer chance, I happen to turn on a debug flag that moves the camera back from the player two units. Literally the poor man's third-person camera. And behold, it was not the worst thing in the world. I finally realize I'm making a third-person game, and so set about implementing it for real. The Culling Saga One of the deadliest scourges of humanity, right after Facebook and taxes, is a third-person camera that constantly zooms and bumps around to avoid in-game geometry. Rather than move the camera, I decide to just cull anything that blocks the camera's view. Half of the job is done right out the gate because my game engine, like most engines, automatically culls triangles that face away from the camera (also known as "back-faces"). I write a shader to handle the rest. It culls everything within a certain distance of the camera. What's that you say? My screenshots look weird with spider bots floating in empty space because the wall got culled? It'll be fine. It's fine. Don't worry about it. What, what now? You can catch glimpses of stuff you're not supposed to see, including the skybox? Look, I'm sure it's just a minor thing. Okay. That's pretty bad. What if instead of carving spheres around the player and camera, I use a cylinder instead? And what if I actually render a solid black cylinder whenever the camera is inside a wall? So close, yet so far. The cylinder blocks out most of the ugly geometry it needs to, but sometimes you can still see through things. I could extend the cylinder to block more, but I would have to clip it so it stays inside the level geometry. Even now, the cylinder sometimes blocks too much, because I only clip it against the player's current wall. Here I only want the cylinder to block the ugly insides of the ledge. Instead it blocks everything behind the player. I would have to query all the geometry surrounding the player and clip the cylinder against all those planes. And that's assuming I can figure out what's "inside" and "outside" the level geometry, which is not air-tight. There are overlapping faces, shapes that clip into each other, and plenty of other lazy hacks— I mean, clever tricks. What if I just turn off back-face culling? Use the same culling shader, and instead of the cylinder, rely on the back-faces to block anything you're not supposed to see. This works perfectly in some cases: Other times it does a great job of showing off my lazy hacks, like this ramp that simply extends into the floor rather than meeting it cleanly: It doesn't help that the back-faces still receive accurate lighting. Feels like the level is a hollow shell. Fine. I'll spend a couple weeks welding level geometry together, and I'll render the back-faces in solid black. How about now? Getting less terrible all the time. With a little depth buffer bias, a special tag in the G-buffer for back-faces, and a few extra texture taps in the composite shader, I can filter out those pesky lines too: The gifs above also show off the new culling shape. Instead of a cylinder, which indiscriminately carves out an uncouth shape much larger than necessary: I switch to a cone, to ensure I only cull things what need culling. But the cone has problems too. It's possible for the player to back up so close to a wall that the cone intersects the wall in an incredibly narrow circle, leaving a tiny hole for the player to peer through. From somewhere deep inside my repressed memories of Calc II springs an exotic mathematical creature known as a paraboloid: A quick trip to the grimoire to remind myself of the formula, a few incantations in a darkened room with a mirror, and the creature is summoned into GLSL form. The culled circle still tapers a little, but it's enough to see fairly well. Good enough for government work. Ship it! UX UX is, like, super important. Take it from me, a full-stack growth-hacking happiness engineer co-founder. Let me tell you about Our Incredible Journey. At first, the game had a terrible retention rate. I did some A/B testing, streamlined the user onboarding, pivoted to clickbait, bought some fraudulent traffic, and now I'm at $10k MRR. I'm also taking cold showers every morning and learning Farsi on Duolingo. If you can keep your eyes from rolling back completely and irreparably inside your head, "User Experience" is a decent descriptor for the interactive aspects of game development, the other contender being "Game Feel". It's the thing you can only get by interacting with the software yourself. It's the thing that makes you smile with surprise when you pick up the controller for the first time, even though you've spent the last hour watching someone else play. It's also basically impossible for me to get right on the first ten tries. Here's an example of my terrible camera UX. When you hit an enemy player without killing them, you bounce off. The camera instantly snaps around to follow your new trajectory. Of course I slerp the rotation a little, but still, you can barely see it happen. I have no reason to lock the camera like this, it's just a carry-over from when the game was first-person, when it made sense to always point the camera where the player was headed next. It takes someone at a convention telling me what an idiot I am to make me finally unlock the camera. A one-line change that takes a whole year. Later, someone on Twitch yells out a self-evidently brilliant suggestion: let the camera lag behind the player a little when they launch. This also takes only a handful of lines to test out, although the numbers don't feel good until a week or two of tweaking. So many of my design decisions are simply carried over from old and outdated assumptions, even though they stopped making sense several versions ago. Here's an example. Remember how I clamp the camera rotation to keep the player from aiming at the surface they're currently attached to? Turns out this gets old after a while, especially in third-person. People want freedom, they don't want you shoving their camera around. I grudgingly loosen the shackles a bit by clamping the rotation against a cone instead of a plane. I use spherical interpolation again to smoothly swing the cone around and nudge the camera away from the wall. Unfortunately, slerp doesn't always rotate the way you want it to. Sometimes the cone pushes the camera in a completely different direction as it rotates to match the surface. Instead of rotating the cone, I decide to instantly snap it to the surface, but scale it up slowly. So it starts as a thin sliver and slowly expands into a fat cone, pushing the camera out as it grows. Everything's going just swimmingly until Momin Khan asks me... is it even necessary to clamp the camera any more? It made sense when the game was first-person, but that was two years ago. I immediately get defensive. How else can I keep the camera from staring straight at the wall for 90% of the game? But I slowly realize he's right. I compromise in the end. I nudge the camera for a split second after landing, then shrink the cone back down to zero to allow glorious unfettered camera freedom. Full range of motion, baybee Now that the player can aim at their currently attached surface, what happens when they try to launch there? I eventually solve this problem by allowing spider bots to "dash" along the surface. I have no physical explanation for how they do it. It's a video game. There's another problem, however. Normally, the game does a raycast starting at the third-person camera and continuing straight through the reticle. When the spider bot launches, it compensates and launches where the player wants it to go, like this: However, sometimes the camera can see and aim at a point the spider bot can't reach. I solve this by ruling everything behind the player's current surface "out of bounds". I even have a shader to darken the forbidden areas. Look, Simba. Everything the light touches is our kingdom. This is really frustrating and confusing to people. Finally Nathan Fouts from Mommy's Best Games tells me to just cheat and let the player go there even if it doesn't make physical sense. I don't like the idea of breaking my game physics so I compromise by having the spider bot dash to the edge and then fly the rest of the way. It all happens so fast, you don't even notice it. Here it is in slow motion: Conclusion Some tasks cannot be sped up. If I had put "make 3D camera" on a Gantt chart, I would have stopped 10% of the way through this article and called it good. The point is, most of these ideas are simple and obvious in hindsight, but I had to make a lot of mistakes to find them. It's nearly impossible to coalesce good design decisions straight from the ether. The only reliable method is iteration and trial and error. Thanks for reading. What embarrassingly obvious design improvements have you been slapped in the face with? Deceiver is set to launch on Kickstarter in early February 2018. Join the mail list to be notified of its release, or check out the source code on GitHub.
  8. 5 points
    Are you asking only about procedural content used IN the game, or do you include procedural generation as a part of the game creation process? Because even games that have static (ie, not generated at run-time) worlds frequently make use of procedural stuff during the creation phases. For example, using algorithms to generate a large chunk of terrain, then using editing tools to make modifications such as building placement, spawn locations, etc.... The procedurals allow the designer to quickly rough-in large areas, rather than forcing them to hand-create every mountain and ridge and valley. Algorithms also allow for more advanced realism, ie an erosion pass on a generated terrain, then using splines to locate roads and rivers and trails. Stuff like that (realistic terrain) is quite difficult to hand-model, but quite easy to model using algorithms as a starting point. I've got a terrain editor in the works that allows to do just that kind of thing. Rapidly generate a terrain from various functions, erode and perform various editing and texturing tasks, place some roads or rivers using splines, then export height and texture blend maps. You can very quickly (ie, in just a few minutes) rough-out a large map. (An example.) As far generation techniques go, I've experimented a bit with some of it and have written about various things over the years in my blog, including generating rock and dirt textures using particle system scattering in Blender, generating a side-scroller level using 3D blocks, generating Minecraft-like block worlds, generating mountain tiles for a 2D game, creating textures from noise functions (more), procedural islands, and so on, and so on. Some of the stuff I've played with have been in-game techniques, but most of it has been for offline content creation stuff. Other techniques I've used include noise functions (quite extensive), tile-based stuff, Wang tiles, architectural grammars, space colonization for procedural trees, meta-tiles (where the 'tile' is a large piece, such as an entire dungeon room, complete with contents), drunkard's walk, labyrinth generation, and many more. Personally, I see procedural generation as a critical part of the game design process, even if only during content creation. With a comprehensive set of rules, you can generate levels for simple puzzle games all the way up to entire open worlds populated with fleshed-out NPCs and monsters.
  9. 5 points
    Couldn't resist, yet another pong clone from me. My twist is that I set the 2D game inside a classic Pong arcade cabinet in VR. Probably disqualifies me, but whatever. Took about 10 hours to build, write up, and upload all the parts. Writeup. Zip file for Windows executable and assets. (39 MB) Video link, seems to be automatically embedded:
  10. 5 points
    Hello! I would like to introduce Diligent Engine, a project that I've been recently working on. Diligent Engine is a light-weight cross-platform abstraction layer between the application and the platform-specific graphics API. Its main goal is to take advantages of the next-generation APIs such as Direct3D12 and Vulkan, but at the same time provide support for older platforms via Direct3D11, OpenGL and OpenGLES. Diligent Engine exposes common front-end for all supported platforms and provides interoperability with underlying native API. It also supports integration with Unity and is designed to be used as a graphics subsystem in a standalone game engine, Unity native plugin or any other 3D application. It is distributed under Apache 2.0 license and is free to use. Full source code is available for download on GitHub. The engine contains shader source code converter that allows shaders authored in HLSL to be translated to GLSL. The engine currently supports Direct3D11, Direct3D12, and OpenGL/GLES on Win32, Universal Windows and Android platforms. API Basics Initialization The engine can perform initialization of the API or attach to already existing D3D11/D3D12 device or OpenGL/GLES context. For instance, the following code shows how the engine can be initialized in D3D12 mode: #include "RenderDeviceFactoryD3D12.h" using namespace Diligent; // ... GetEngineFactoryD3D12Type GetEngineFactoryD3D12 = nullptr; // Load the dll and import GetEngineFactoryD3D12() function LoadGraphicsEngineD3D12(GetEngineFactoryD3D12); auto *pFactoryD3D11 = GetEngineFactoryD3D12(); EngineD3D12Attribs EngD3D12Attribs; EngD3D12Attribs.CPUDescriptorHeapAllocationSize[0] = 1024; EngD3D12Attribs.CPUDescriptorHeapAllocationSize[1] = 32; EngD3D12Attribs.CPUDescriptorHeapAllocationSize[2] = 16; EngD3D12Attribs.CPUDescriptorHeapAllocationSize[3] = 16; EngD3D12Attribs.NumCommandsToFlushCmdList = 64; RefCntAutoPtr<IRenderDevice> pRenderDevice; RefCntAutoPtr<IDeviceContext> pImmediateContext; SwapChainDesc SwapChainDesc; RefCntAutoPtr<ISwapChain> pSwapChain; pFactoryD3D11->CreateDeviceAndContextsD3D12( EngD3D12Attribs, &pRenderDevice, &pImmediateContext, 0 ); pFactoryD3D11->CreateSwapChainD3D12( pRenderDevice, pImmediateContext, SwapChainDesc, hWnd, &pSwapChain ); Creating Resources Device resources are created by the render device. The two main resource types are buffers, which represent linear memory, and textures, which use memory layouts optimized for fast filtering. To create a buffer, you need to populate BufferDesc structure and call IRenderDevice::CreateBuffer(). The following code creates a uniform (constant) buffer: BufferDesc BuffDesc; BufferDesc.Name = "Uniform buffer"; BuffDesc.BindFlags = BIND_UNIFORM_BUFFER; BuffDesc.Usage = USAGE_DYNAMIC; BuffDesc.uiSizeInBytes = sizeof(ShaderConstants); BuffDesc.CPUAccessFlags = CPU_ACCESS_WRITE; m_pDevice->CreateBuffer( BuffDesc, BufferData(), &m_pConstantBuffer ); Similar, to create a texture, populate TextureDesc structure and call IRenderDevice::CreateTexture() as in the following example: TextureDesc TexDesc; TexDesc.Name = "My texture 2D"; TexDesc.Type = TEXTURE_TYPE_2D; TexDesc.Width = 1024; TexDesc.Height = 1024; TexDesc.Format = TEX_FORMAT_RGBA8_UNORM; TexDesc.Usage = USAGE_DEFAULT; TexDesc.BindFlags = BIND_SHADER_RESOURCE | BIND_RENDER_TARGET | BIND_UNORDERED_ACCESS; TexDesc.Name = "Sample 2D Texture"; m_pRenderDevice->CreateTexture( TexDesc, TextureData(), &m_pTestTex ); Initializing Pipeline State Diligent Engine follows Direct3D12 style to configure the graphics/compute pipeline. One big Pipelines State Object (PSO) encompasses all required states (all shader stages, input layout description, depth stencil, rasterizer and blend state descriptions etc.) Creating Shaders To create a shader, populate ShaderCreationAttribs structure. An important member is ShaderCreationAttribs::SourceLanguage. The following are valid values for this member: SHADER_SOURCE_LANGUAGE_DEFAULT - The shader source format matches the underlying graphics API: HLSL for D3D11 or D3D12 mode, and GLSL for OpenGL and OpenGLES modes. SHADER_SOURCE_LANGUAGE_HLSL - The shader source is in HLSL. For OpenGL and OpenGLES modes, the source code will be converted to GLSL. See shader converter for details. SHADER_SOURCE_LANGUAGE_GLSL - The shader source is in GLSL. There is currently no GLSL to HLSL converter. To allow grouping of resources based on the frequency of expected change, Diligent Engine introduces classification of shader variables: Static variables (SHADER_VARIABLE_TYPE_STATIC) are variables that are expected to be set only once. They may not be changed once a resource is bound to the variable. Such variables are intended to hold global constants such as camera attributes or global light attributes constant buffers. Mutable variables (SHADER_VARIABLE_TYPE_MUTABLE) define resources that are expected to change on a per-material frequency. Examples may include diffuse textures, normal maps etc. Dynamic variables (SHADER_VARIABLE_TYPE_DYNAMIC) are expected to change frequently and randomly. This post describes the resource binding model in Diligent Engine. The following is an example of shader initialization: ShaderCreationAttribs Attrs; Attrs.Desc.Name = "MyPixelShader"; Attrs.FilePath = "MyShaderFile.fx"; Attrs.SearchDirectories = "shaders;shaders\\inc;"; Attrs.EntryPoint = "MyPixelShader"; Attrs.Desc.ShaderType = SHADER_TYPE_PIXEL; Attrs.SourceLanguage = SHADER_SOURCE_LANGUAGE_HLSL; BasicShaderSourceStreamFactory BasicSSSFactory(Attrs.SearchDirectories); Attrs.pShaderSourceStreamFactory = &BasicSSSFactory; ShaderVariableDesc ShaderVars[] = { {"g_StaticTexture", SHADER_VARIABLE_TYPE_STATIC}, {"g_MutableTexture", SHADER_VARIABLE_TYPE_MUTABLE}, {"g_DynamicTexture", SHADER_VARIABLE_TYPE_DYNAMIC} }; Attrs.Desc.VariableDesc = ShaderVars; Attrs.Desc.NumVariables = _countof(ShaderVars); Attrs.Desc.DefaultVariableType = SHADER_VARIABLE_TYPE_STATIC; StaticSamplerDesc StaticSampler; StaticSampler.Desc.MinFilter = FILTER_TYPE_LINEAR; StaticSampler.Desc.MagFilter = FILTER_TYPE_LINEAR; StaticSampler.Desc.MipFilter = FILTER_TYPE_LINEAR; StaticSampler.TextureName = "g_MutableTexture"; Attrs.Desc.NumStaticSamplers = 1; Attrs.Desc.StaticSamplers = &StaticSampler; ShaderMacroHelper Macros; Macros.AddShaderMacro("USE_SHADOWS", 1); Macros.AddShaderMacro("NUM_SHADOW_SAMPLES", 4); Macros.Finalize(); Attrs.Macros = Macros; RefCntAutoPtr<IShader> pShader; m_pDevice->CreateShader( Attrs, &pShader ); Creating the Pipeline State Object To create a pipeline state object, define instance of PipelineStateDesc structure. The structure defines the pipeline specifics such as if the pipeline is a compute pipeline, number and format of render targets as well as depth-stencil format: // This is a graphics pipeline PSODesc.IsComputePipeline = false; PSODesc.GraphicsPipeline.NumRenderTargets = 1; PSODesc.GraphicsPipeline.RTVFormats[0] = TEX_FORMAT_RGBA8_UNORM_SRGB; PSODesc.GraphicsPipeline.DSVFormat = TEX_FORMAT_D32_FLOAT; The structure also defines depth-stencil, rasterizer, blend state, input layout and other parameters. For instance, rasterizer state can be defined as in the code snippet below: // Init rasterizer state RasterizerStateDesc &RasterizerDesc = PSODesc.GraphicsPipeline.RasterizerDesc; RasterizerDesc.FillMode = FILL_MODE_SOLID; RasterizerDesc.CullMode = CULL_MODE_NONE; RasterizerDesc.FrontCounterClockwise = True; RasterizerDesc.ScissorEnable = True; //RSDesc.MultisampleEnable = false; // do not allow msaa (fonts would be degraded) RasterizerDesc.AntialiasedLineEnable = False; When all fields are populated, call IRenderDevice::CreatePipelineState() to create the PSO: m_pDev->CreatePipelineState(PSODesc, &m_pPSO); Binding Shader Resources Shader resource binding in Diligent Engine is based on grouping variables in 3 different groups (static, mutable and dynamic). Static variables are variables that are expected to be set only once. They may not be changed once a resource is bound to the variable. Such variables are intended to hold global constants such as camera attributes or global light attributes constant buffers. They are bound directly to the shader object: PixelShader->GetShaderVariable( "g_tex2DShadowMap" )->Set( pShadowMapSRV ); Mutable and dynamic variables are bound via a new object called Shader Resource Binding (SRB), which is created by the pipeline state: m_pPSO->CreateShaderResourceBinding(&m_pSRB); Dynamic and mutable resources are then bound through SRB object: m_pSRB->GetVariable(SHADER_TYPE_VERTEX, "tex2DDiffuse")->Set(pDiffuseTexSRV); m_pSRB->GetVariable(SHADER_TYPE_VERTEX, "cbRandomAttribs")->Set(pRandomAttrsCB); The difference between mutable and dynamic resources is that mutable ones can only be set once for every instance of a shader resource binding. Dynamic resources can be set multiple times. It is important to properly set the variable type as this may affect performance. Static variables are generally most efficient, followed by mutable. Dynamic variables are most expensive from performance point of view. This post explains shader resource binding in more details. Setting the Pipeline State and Invoking Draw Command Before any draw command can be invoked, all required vertex and index buffers as well as the pipeline state should be bound to the device context: // Clear render target const float zero[4] = {0, 0, 0, 0}; m_pContext->ClearRenderTarget(nullptr, zero); // Set vertex and index buffers IBuffer *buffer[] = {m_pVertexBuffer}; Uint32 offsets[] = {0}; Uint32 strides[] = {sizeof(MyVertex)}; m_pContext->SetVertexBuffers(0, 1, buffer, strides, offsets, SET_VERTEX_BUFFERS_FLAG_RESET); m_pContext->SetIndexBuffer(m_pIndexBuffer, 0); m_pContext->SetPipelineState(m_pPSO); Also, all shader resources must be committed to the device context: m_pContext->CommitShaderResources(m_pSRB, COMMIT_SHADER_RESOURCES_FLAG_TRANSITION_RESOURCES); When all required states and resources are bound, IDeviceContext::Draw() can be used to execute draw command or IDeviceContext::DispatchCompute() can be used to execute compute command. Note that for a draw command, graphics pipeline must be bound, and for dispatch command, compute pipeline must be bound. Draw() takes DrawAttribs structure as an argument. The structure members define all attributes required to perform the command (primitive topology, number of vertices or indices, if draw call is indexed or not, if draw call is instanced or not, if draw call is indirect or not, etc.). For example: DrawAttribs attrs; attrs.IsIndexed = true; attrs.IndexType = VT_UINT16; attrs.NumIndices = 36; attrs.Topology = PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; pContext->Draw(attrs); Build Instructions Please visit this page for detailed build instructions. Samples The engine contains two graphics samples that demonstrate how the API can be used. AntTweakBar sample demonstrates how to use AntTweakBar library to create simple user interface. It can also be thought of as Diligent Engine’s “Hello World” example. Atmospheric scattering sample is a more advanced one. It demonstrates how Diligent Engine can be used to implement various rendering tasks: loading textures from files, using complex shaders, rendering to textures, using compute shaders and unordered access views, etc. The engine also includes Asteroids performance benchmark based on this demo developed by Intel. It renders 50,000 unique textured asteroids and lets compare performance of D3D11 and D3D12 implementations. Every asteroid is a combination of one of 1000 unique meshes and one of 10 unique textures. Integration with Unity Diligent Engine supports integration with Unity through Unity low-level native plugin interface. The engine relies on Native API Interoperability to attach to the graphics API initialized by Unity. After Diligent Engine device and context are created, they can be used us usual to create resources and issue rendering commands. GhostCubePlugin shows an example how Diligent Engine can be used to render a ghost cube only visible as a reflection in a mirror.
  11. 5 points
    Generally a level designer starts with a "white box" or "gray box" world, where barriers and stuff are filled with simple placeholders. 3D modeling and texturing are art roles, necessary skills if you are planning on being a game artist. Good level design is hard, and does not require the fancy models or textures to build. Simple boxes and primitives should be enough to begin navigating and evaluating the level even though it may not have the full visual feel. Good level design is difficult. In single player levels, building worlds that provide an amazing growth curve and implicit tutorial. In multi-player games building worlds that provide complex environments that are fair for all sides, providing different yet fair opportunities for everyone, that can be learned quickly and easily yet are always off-balance so advantages can be had but can also be readily overcome. As you are looking for an entry into the game field, level designer is an extremely rare job. A studio may run for several projects in a row without hiring any. Higher level designers can often design the worlds to fit their mechanics and pass it over to artists to flesh out. Art roles are extremely common jobs, usually a few are hired every project both as the studios grow and as people naturally change jobs.
  12. 5 points
    Following along from the previous post about the node graphs, I have lately pulled the node graph stuff out and have started work also on a standalone editor for noise functions. https://github.com/JTippetts/ANLEditor The editor uses the node graph functionality, along with an output node that provides various functions, to allow one to create graphs of noise that can be used to create textures. The output node allows you to map either a Grayscale or RGBA image output (the Volume button currently does nothing, for now). It can analyze a connected grayscale function to give you a histogram graph of how the function output is distributed, and calculates a set of scale/add factors that could be used to remap the output of the function to the 0,1 range. It allows you to specify seamless mapping settings, and to export images to file. It's all still fairly rudimentary and I still haven't settled on a final save/load format, but all that is in progress. I have also started creating an editor of sorts for Goblinson Crusoe, using some of this editor functionality. It's still in its infancy, but eventually it will allow me to create areas and area pieces for use in randomly generating maps. Lately, I've been doing some thinking about what I want to do with Goblinson Crusoe. It has become clear to me that it will probably never be a commercial release. It will probably never be on Steam or anything like that. I just don't have the time. I wasted a LOT of my early years spinning my wheels and going nowhere, and now I have so many other things that have to come first (family, full-time job, home-ownership, etc...) that I just don't think I'd ever realistically finish this thing. If I could work on it full-time, perhaps, but mortgage, bills, and the necessity of providing insurance and safety nets for my wife and kids means that isn't feasible. However, I do enjoy working on it, and don't want to just abandon it. Nor do I want it to never see some kind of release. And I would like to see some kind of return on my huge time investment over the years. So I've been thinking of making GC a free and open-source project, linked with a Patreon and/or PayPal for goodwill donations. At least that way, if I die or life gets in the way of further development, at the very least it wouldn't disappear completely. Plus, I might get at least a few dollars from appreciative people along the way. What do you all think? Any advice on how to structure such a thing? Good idea/bad idea?
  13. 5 points
    This sounds really bad. GPUs have been moving away from specialized hardware and towards general purpose hardware forever. You'd be better off running whatever this algorithm is on the GPU than on another chip... And if your GPU is too weak, put that extra $140 into getting a better one than a fancy chip. The only valid use case seems to be optionally adding extra image processing to old fixed hardware (consoles). If you're talking about building the hardware into a GPU, then again you're probably better off dedicating that space to more compute cores, and adding any extra fixed-function behavior that it requires into the existing fixed-function texture sampling/filtering hardware. That way games can decide to use a different AA method and not have some fixed-function AA chip sitting idle -- the extra compute cores are running the game's own AA solution. Or if it does have some fancy fixed function filtering, then by integrating this into the existing texture filters, then you allow developers to use that hardware on other algorithms too (not just post processing). As for upscaling though, yeah GPUs sometimes to have a hardware upscaler built into the video output hardware. Microsoft is a fan of making sure the hardware upscaler is as good as possible... so there may be some room to add some smarts into that... but on PC, it's not common to render at 480p any more and have the GPU upscale to 1080p output... Secondly, there's two kinds of anti-aliasing techniques - ones that avoid aliasing in the first place (toksvig, increased sampling + filters) and ones that try to hide aliasing after it's occurred (FXAA, etc). The latter aren't a solution, they're a kludge, and they're not the future. The biggest problem with filters like FXAA is that they're not temporally stable. Jaggies get smoothed out, but "smooth jaggies" still crawl along edges. The current state of the art in geometric AA involves extra samples (MSAA + temporal) and smart filters. This kind of of external add on can never have access to that extra information, so is doomed to FXAA style kludge filtering. The current state of the art in specular aliasing attacks the problem at the complete other end of the pipeline - filtering before lighting calculations. An add on can never do that. [edit] Watched the video, and yeah, it's smoothing jaggies but in no way solving aliasing. This kind of flickering is everywhere:
  14. 5 points
    Hi everybody! I decided to use this challenge as an excuse for learning to use Game Maker (or I wanted to learn Game Maker and decided to do it while participating in this challenge; pick one :P). My project is called "Power Word: Pong". It's available for Windows here: https://racso.itch.io/power-word-pong I still want to improve the AI, as it's still quite dumb, and I want to give some variety to the ball (angle and speed changes), but I'm almost done with the game. Still, as always, feedback is appreciated! I hope you like the twist of the game. You may find the game source in this repository. I'll create a post-mortem after I finish working in the project. Regards! O.
  15. 4 points
    Because there was no internet before the net neutrality rules, right?
  16. 4 points
    That approach is extremely common in my experience, except typically with as-small-as-possible ID's instead of GUIDs (even u8 if you know you won't instantiate a particular class 256 times!). You typically don't do a search, but a simple lookup into an array that holds the indices. e.g. struct NonMovableComponents { int alloc() { return /*next unused component slot*/; } T& operator[]( int i ) { return component[i]; } T component[SIZE]; }; struct MovableComponents { int alloc() { int slot = /*next unused indices slot*/; int index = /*next unused component slot*/; indices[slot] = index; return slot; } T& operator[]( int i ) { return component[indices[i]]; } T component[SIZE]; int indices[SIZE]; }; However... whether this is an issue depends a lot on how you're using your "components". In some games, the primary way that components are accessed is by iterating over all of them -- for each component, do x... If this case, the cost of a lookup from an entity's handle doesn't matter, because you don't do it very much. In other games, the primary way that components are accessed is from their parent entity -- entity->GetComponent<Transform>()->DoX()... In this case, sure, you want those lookups to be fast... but you've probably also got bad access patterns anyway, so you're not going to get as much benefit from defragging, so you could just, not defrag After the defrag operation, you could go and patch all your component pointers. Entities could listen for an "on defrag" event from systems that they have pointers into.
  17. 4 points
    Spellbound is intended to be a story driven game. I feel that's the only thing which can make the game interesting on its own. The story of Spellbound has gone through a lot of evolutionary changes throughout the development process. When I initially conceived of the game, I just had a game concept: "Throw fireballs at zombies in VR, using your hands". As a game premise, that's mildly interesting but it would quickly lose its novelty and appeal. How do I make it interesting? I needed a story. Initially, my writing approach was to ask hard questions about the world: Why are there zombies? Where did they come from? Why is the wizard in a zombie infested graveyard? What's going through the wizards mind? What was his life like? What was his past? So, I tried to find answers which made sense, given that you're just some red cloaked dude in a wizard hat, slinging fireballs at zombies. The first version of the game and story was embarrassingly bad. The synopsis of the story: "You were a wizard whose wife had died, and you were searching for a way to bring her back to life because you missed her. So, you casted a spell promising to bring her back to life via resurrection, but instead, it just reanimated her and turned her into a zombie. The spell worked so well, that it also brought all of the corpses in the nearby graveyard to life as well! Your undead wife flees to the graveyard, so you have to defeat infinite waves of undead zombies. After a while, you face a big boss monster who was behind it all!" As far as stories go, that was pretty pathetic but also short. I'm a half decent writer with imagination, I know I can do better if I just spent some time to work something out. I needed to ship something playable to people, quickly. I thought that the main map would be my main game play, but it wasn't completed yet and ready for public consumption (it didn't satisfy my quality standards). So, I created an early "prelude" level. I also needed a main menu in VR, and since this is needs to be a seamless experience between game world and game menu, the menu itself can't be a static 2D screen like you'd have in traditional 2D games -- the menu itself had to be a level which you interact with. I was ruminating on story in the back of my mind for a while at this point, and I decided that I eventually wanted to have five wizards, each from a different school and theme of magic, each with unique story lines. My game universe was growing in complexity. But, I can't focus on developing the story. I need to ship as soon as possible to get something playable out there! I had chosen the "Red Wizard" as the first school of magic and theme to focus on. I didn't know what the story would really be, but I had written a really rough outline which served as a rough map on where I wanted to go with the plot. I would come back to the story much later and flesh it out, but for now, I just needed to create the prelude story and introduce players to the game universe and introduce a character or two. I wrote the prelude story in a day, polished the dialogue, and kept it somewhat vague, but also left a cliff hanger as a lead in for the main story. Then I shipped it. Currently, you can still only play the prelude and experience that story, and its short at best, but it shows the story telling model I'm using for VR: 1. I introduce an illustrated storybook and a narrator reads the first six pages. This serves as an establishing shot / context, and also establishes the narrator. 2. I fade to black, load the game world, fade in, and the story resumes from the first person perspective. The wizard talks to himself as a way to guide the player on what to do (a bit weird), and the narrator adds story as well, sort of like how a dungeon master would. 3. At the end of the VR experience, we fade to black and return to the library menu, and resume reading 1-2 illustrated pages as sort of an "epilogue", which can serve as a seamless lead-in for the next story. This month, I decided that I was a bit too aimless with my development and I needed to get more focused on shipping the next set of content. Okay, where do I begin? I don't have a level made, no story, barely any functioning spells, no crafting system, etc. What have I been wasting my time on?? Oh right, an AI system with machine learning. I realized that the pragmatic thing to do is stop everything else and focus on fleshing out the story for the red wizard. Once I have the story complete, I'll have a much better idea on the scope of the project, what scenes need to be built, what's important and what's not important, and I can start focusing on actually building my game around the story. This seems like an obviously good idea in hindsight. The story is like my game design document, and if the scope is too big, I can change the story until its achievable. So... I just have to write the story. The problem is, I just had a really rough outline on what I think the story should be about. Despite the outline, I actually don't know what the story is. Okay, so how do I figure that out? I just have to start writing. But, I can't just start writing blindly! I need to spend some time crafting the world, the characters, the history, the lore, etc! My approach to writing my story is to write out the very best first draft that I can, as completely as I can. The point is not to have a story ready for production, but to just figure out what the story is. What story am I trying to tell? Why is it interesting? What captures the readers attention and holds it? What can the audience get out of the story? What makes the story emotional? What creates a sense of wonder and amazement? What are the high points and low points of the story? Who are the protagonists? Who are the antagonists? Who are the supporting characters? What is every characters motive? Every character needs to have a flaw to be interesting, so what are the character flaws? How do those flaws get revealed? How does the character flaw play into the story? How does the story begin? What's the problem the characters are trying to solve? What's the struggle? How do the characters overcome the problem? How does the character need to grow in order to overcome the problem? How does the problem get resolved? How does the character feel about the resolution(s)? How does the audience feel about the resolution? How do we set ourselves up for introducing the next episode? Oh, and by the way, all of this has to be done in VR so we have to assume that the protagonist has total agency over decisions made, so story has to account for that. It's a bit of an overwhelming puzzle to work out. It's extremely important to note that since my game is going to be story driven, where the story either makes or breaks the final result, I cannot afford to half heartedly write a mediocre story. I have to write the greatest story I'm capable of writing. My game depends on it. The future of my one man company depends on it. My income depends on it. The story is the backbone. It's my secret sauce. My secret weapon. It's going to be what makes it a "must have" for every VR gamers library. And it can't just be a story which was shoved into a VR game, it has to be a story built from the ground up, specifically for VR, to make use of the unique story telling capabilities VR offers. So, I cannot just write out a first draft, call it good, and move forward with production. If it takes two weeks or two months to get the story perfect, then so be it. So, I'm thinking that I'm a bit of a novice when it comes to story writing. I have never published a novel. Never wrote a screen play. Never wrote a story for a game. At best, I've written a few short stories for a community college class. But, I have good story ideas, damnit! That's my stubbornness and ego peeking through, insisting that despite my lack of experience, I'm more qualified than anyone else to be the one who writes the story. How do I account for my lack of experience with "officially" not being published? I say, "It doesn't matter, I don't care, fuck it, I will just have to write 20 drafts to be on par with a professional." I think that's the right intuition though: Write 20 drafts of the same story. The first few drafts are going to be exploratory. You don't know what the story is until you've written it. You don't know who the characters are yet. You don't know their motives. The first version of the story is just a congealing of the oatmeal, where you bring it all together and sort of figure out what the real story is. This is where you answer all of the questions I listed above. You might need to write several versions of the story. Think of each version as sort of like a parallel universe, where each version can explore different possibilities in plot development. Eventually, you'll find that you're drawn to certain plot highlights and themes more strongly than others, and those become your story. At this point, you have written your story about 3-5 times. You're familiar with it, but not intimately. Now, the story becomes more like sheet music to you (the author), and it's a bit of an unfamiliar song. You can kind of play the notes and create a semblance of what the song sounds like, but it's rough and spotty. You know what notes you need to hit and when, so the only way to properly hit those notes is to practice, practice, practice. This means you're going to be rewriting your story, over and over again, each time getting more and more familiar with the plot. There isn't a fixed number of times you need to rewrite the story, but you'll know when you've written the final version: It'll flow like beautiful music off the paper, wrapping the reader in a warm hug before fleeting away. The reader will be embraced in a feeling of warmth and happiness for a moment, and then left wanting more, more, more. You've now got a page turner. A novel people can't put down. A movie which demands your attention. A game people can't stop. What happens next?! ...Turn the page to find out! I was recently encouraged by a blog article I read on the writing process of William Shakespeare. Most people think that his writings was pure genius, written from divine inspiration, and it just flowed to him easily via unnatural talent. Historical records of his writings show that actually... he wrote many, many revisions of his plays over the years. Even Shakespeare wasn't some savant writer who wrote perfect first drafts, and he's considered to be the best writer in the history of the English language. But I realized that I can't just start writing successively better iterations of the same story. There's SO much more to the story world than what people read on the pages. You know how when you pick up some fantasy books, and on the first page they have a map of the world, with kingdoms, city names, mountain ranges, rivers, oceans, and all of that stuff laid out? There is a whole story universe which the story events are set within! Each kingdom may have different politics. Different cultural customs. Different building construction aesthetics. Different values. Those background differences will and should make an impact on the story as its being told! Is slavery legal in one kingdom but not another? How does the climate affect clothing and customs? How does a traveler from one kingdom deal with the differences in culture in another? Is it a source of character conflict? What are the motives of each kingdom and its political leadership? What is the history which shaped the current state of the world? How does the past factor into any current conflicts? There's a LOT more investigatory questions to ask, but you get the idea. I realized that this narrative background stuff is very important to establish! It is literally the foundation upon which your story rests. The presence of this background scaffolding may never actually manifest in your story directly, but it is the world which contains your narrative events. If you don't build the world, your story doesn't rest on anything solid and it will be very wishy washy. So, before I started earnestly writing my actual story, I spent a lot of time writing about the world and its history. When you read my story, you are only experiencing 10% of the universe/work. The other 90% was scaffolding which was put into place, and then stripped away when it was no longer needed. People will just see the finished product and think, "Oh wow, this looks easy. I bet they just started writing from pure inspiration!", but that illusion is so far from the truth of the underlying writing process. I spent nearly a week just writing scaffolding background material. What are all the races? What are they like? What are their values? What institutions exist in the world? What is the history of the institutions? What is the common sentiment in the kingdoms? What landmarks exist? Why are they important? What creatures exist? What's their lore and background? etc. etc. You know what? I'm glad I did this. It created a nice background framework for me to work within. I, the writer, know everything about the Academy of Magic, who's really running it, where it's located, and its deep history, but the reader gets to discover little tidbits about this institution and they can gradually put it together like a puzzle. At the end, the reader may not know everything there was to know about the Academy of Magic, but maybe there will be more content later which brings those interesting details to the surface? Just think about it: How much did you know about Hogwarts after the first Harry Potter book? How much did you really know about Luke Skywalker after only watching Episode IV: A new hope? And after you experienced all of the content and had a better understanding of the world, and then watched it again, how much more sense did the actions of the characters make when you understood the background context? Anyways, I'd like to share with you a few select pieces of narrative content I've worked on recently. Keep in mind, all of this is first draft material, so there's a high likelihood that the 20th version will be very different: ~~STORY BOOK OPENS~~ Page 1: [Narrator]: “The legend of Rupert the Red… goes something like this” [Narrator]: “Over three thousand years ago, there was a grand battle between magicians of ages past. They nearly ruined the world, but instead, they set civilization back by thousands of years.” *Picture of wizards at war, volcanoes exploding, land tearing up, red sky* Page 2: [Narrator]: “The kings of old, never forgot the calamity. They unanimously decreed that henceforth…” [Kings voice]: “all magic must be banned. Those caught practicing sorcery, shall be put to death!” *Picture of kings sitting around a round table, one king is standing and leaning forward with a raised fist, addressing the other kings* Page 3: [Narrator]: And kingdoms across the lands, knew peace... With the exception of magicians. [Angry crowd]: “Burn the witches! Burn them all!” [Narrator]: “But while magicians and sorcerers can be hunted and killed, magic itself can never be extinguished. What the kings of old didn’t quite understand, is that magic itself is a gift bestowed upon mortals by the gods themselves. Oh, how they tried to kill magic though.” *Picture of an angry mob with torches and pitchforks, surrounding posts with silhouettes of people tied to them, as a massive fire burns them* Page 4: [Narrator]: The gift of magic was a sliver of the gods themselves, given to mortals to fight against darkness. When darkness came again, the kingdoms were defenseless and fell like wheat to the scythe. [People] : *anguished screams of terror* [Monsters] : *roaring, gnashing and slashing* *Picture of men, women and children being chased and killed by demon spawn. Sky is red, filled with smoke. The face of a grinning devil can be faintly seen in the clouds* Page 5: [Narrator]: A few sorcerers who had evaded the murderous clutches of men, stood united against darkness and sealed it away at heavy cost. [Magician Group]: Chanting in unison *Picture: 5 men and women, holding hands in a circle, with red, blue, white, black and green magical flame pillars, and connected lines of magical color in a star pentagram shape. In the center, stands an old man (Sassafras). Page 6: [Narrator]: The kingdoms were safe again, but the kings… they blamed the magicians for their destruction. *Picture of a group of soldiers nailing wanted posters to lamp posts* (Hammering sounds) Page 7: [Narrator]: A young boy, with the reddest hair you’d ever see, was born to a pair of humble farmers living on the edge of the Black Forest. [Baby] : Crying sounds *Picture of a crying baby being held in the arms of a mother, with a red shock of hair on its head* Page 8: [Narrator]: His father named him “Rupert”. The boy grew up, as all young boys do, and trouble followed naturally, as it does with all young boys. *Squealing pig noises and boyish laughing sounds* *Picture of a young freckle faced farm boy with a pot on his head, chasing a terrified pig with a stick* Page 9: [Narrator] : But, as fate would have it, the natural troubles of boyhood soon turned into supernatural troubles which only followed Rupert. *burning house & inferno sounds, screams* [Narrator] : Rupert was a magician. The villagers were afraid and angry. [Villagers]: “Rupert is cursed! He’s a witch! Burn him!” Page 10: [Narrator]: Rupert ran, and he ran, and he ran, deep into the black forest. The village hunters eventually gave up. (picture of rupert hiding under a stump while a dog search party with torches looks for him in the distance) *barking sounds in the distance* Page 11: [Narrator]: Rupert wandered through the forest for days, getting hungrier and hungrier. He stumbled on an old, broken tower of mossy stone, and made it his home. He lived on bark and berries. *picture of a young boy trying to eat bark in a forest, with teeth almost breaking against it* Page 12: [Narrator]: He lived for years, completely alone, terrified of the supernatural troubles which seemed to follow him everywhere. [Narrator]: Last night, Rupert discovered a book as old as time: The lost book of Sassafras. He was about to change the course of history -- FOREVER. *Picture of Rupert sleeping soundly on his back, with drool coming out of his mouth. A black crow with red eyes watches.* Snoring noises, followed by “Caw, caw! Caw!” from the crow. ~~FADE TO BLACK FROM STORYBOOK MODE, FADE INTO GAME VIEW~~ Note: Cawlin has somewhat of a German accent. [First morning, wake up] Rupert is sleeping in his bed after his late night journey into the undead infested crypts. He has been sleeping restfully for 11 hours and it is now nearly noon. An impatient crow stands at the foot of his bed. RR: "ZZZzzzz...ZZZzzz...huuuurffffgll, guuurffflllghh..." (deep snoring) Cawlin: "Cawww... Cawww... Cawkadoodlydoo! Wake up, you!" RR: "ZZZz---huh? Who said that?! Who's there?!" Rupert awakens slowly, the VR camera opens eyelids slowly, blinking awake. The player is looking down the foot of the bed at the crow. Cawlin: "Caww.." RR: "Oh… it’s just a stupid bird." Bird cocks it head to the side in curiosity. Cawlin: "Caww?" RR: "Oh, just listen to me. I'm already going mad -- first it starts with talking to the birds, then its rocks and then its trees." Cawlin: "Caw!" RR: "Say now, how did you manage to get in here? I didn't leave a window or door open last night, did I?" Cawlin: "Caw… Caw..." We wait for the player to get out of bed. They can either click the bed or walk out of the bed zone. Once they move out, we quickly fade to black and fade back in, to the wizard standing at the bedside. RR: "If I'm going to be a raving madman talking to bird brains, you must ... have a name... I shall call you..." Cawlin: "Caw... Cawlin." RR: "...Cawlin." Cawlin: "Caw! It's about time you got up, it’s well past noon! And just who might yewwwww be??" RR: "What?! A talking bird?! Now, I've certainly gone mad!" Cawlin: "Yes, yes, you’re a certified loon and I’m a crow.” (rolls eyes) Cawlin: “Now that we’ve gotten that out of the way, who are you?" RR: "Well...I'm Rupert!” Cawlin: "RRRrrrrupert… what is it that you’re doing in these woods?" RR: "This is my home! I live here." Cawlin: "Ho… how unusual... a huuuuman living in the black forest..." RR: "Unusual? ...Why?" Cawlin: “Humans haven’t ventured into the black forest for centuries. Those that do… never come out alive. There’s something… peck-uliar about you Rupert… What ees it?” *Rupert feels afraid for a moment because his secret about being magical might be given up* RR: “I… I don’t know what you’re talking about.” Cawlin: “No, there’s definitely something about you…. I can… smell eet… ah, there eet ees again! You’re… magical!” RR: “...Magical? I don’t believe in magic...” Cawlin: “You fool! Here you are, speaking with a talking bird, and you don’t believe in magic? I watched you last night as you rrrRRrroasted the walking dead with fi-yar.” RR: “Wait, you were there? You saw that?! It was real?!” Cawlin: “Of course I was... I had been waiting for you... all night! Quite the pyrrrrrotechic display, if I might say.” RR: “I still can’t quite believe what I saw. I almost thought it was just a bad dream -- I just -- haven’t been sleeping well lately.” Cawlin: “Yes, yes, it was all real. No matter! … Eet has come to my attention… that you have acquired a certain… book.” (pronounced almost like “buch”) RR: “Yeah, it was a really weird book… I heard it speak! A strange voice called out to me.” (Cawlin jumps up and down in excitement, flapping his wings) Cawlin: “Ah… do you know what you’ve found? Theees ees sooo exciting! You’ve finally found eet!” RR: “Ehh… what?” Cawlin: “The buch! The long lost book of Sassafraaaaaas! …. Eets verrry special to me. I must see it!” RR: “What’s so special about this book?” Cawlin: “Oh, eet ees only the most powerful buch of magic in the heestory of the world! It has been lost for thousands of years, but lost eet ees no more! You have eet! Eet is very special.” Cawlin: "Thees book, you know, it doesn't just get found by anyone. It... choooooses... Yes, that's the right word.. The book chooses ... who it uses. Many wizards think they use books, but never does it occur to them that the book uses them! Sassafras was it's last chosen wizard, and that was thousands of years ago! And last night, it seems to have chosen… RRRrrrrrrupert. Now, ...Why did it choose rupert?!" RR: "I don't know! I barely know anything about magic.” Cawlin: “The book must have it’s own reasons… muahahahaha” RR: "So, what now?" Cawlin: “We must read the magic buch, of course! Let’s go find eet!” Cawlin jumps onto the left shoulder of Rupert. There is no further dialogue until the player goes downstairs. A large book sits prominently on a table next to the door. It is sparkling and glowing, softly illuminating the darkness with red light. Cawlin: “Oh… there eet ees! ...thees ees so wonderful. I can feel eet… so close… yet so far.” (said in a deeper ominous voice) Cawlin flies from the wizards shoulder to go over to look at the book on the table. This helps direct the players attention. RR: “oooh...kay…” (said in the tone of, “who is this bird?”) Cawlin: “Open eet! Let’s see what secrets eet contains!” We wait for the wizard to use the book. When he uses it for the first time, the book opens and a bunch of green energy swirls from the book to the wizard. Upon the pages of the book is nothing but symbols and gibberish. RR: “What was that?!” Cawlin: “I don’t know. Magic maybe? Who cares, read the book!” Cawlin: “Well? What does eet say? What do you see?” RR: “It’s just a bunch of symbols and gibberish. I can’t read any of this!” Cawlin: “What?! Oh no...I hadn’t counted on thees. Why did eet have to be him? ... Why?” RR: “What? What do you mean?” Cawlin: “You… you don’t actually know magic. Not yet, at least.” RR: “I don’t? How is that possible? I was just throwing fireballs last night.” Cawlin: “Ahem… yes… you’re welcome for thee assistance.” RR: “Uh… what?” Cawlin: “That fire essence you used last night… I put eet there for you. Eet was just a temporary conduit for your latent magics… You don’t *actually* know how to use magic yet...” RR: "Okay, so what? How do I read this book?" Cawlin: "I don’t know. I’m just a bird, I can’t read!" RR: “So… then this book is useless to both of us.” Cawlin: “Maybe you can find a clue which could help us?” Cawlin flies back onto the left shoulder of the wizard. When the player walks away from the spellbook, it disintegrates in a puff of green particles. RR: “What happened to the book?! Where did it go?” Cawlin: “Oh… amazing! …Eet’s bound to your magical spirit. Eet ees always with you!” RR: “I don’t understand.” Cawlin: “The buch! You can call eet back at any time, and you will never lose eet! Try it now… Just focus on a hand, imagine the book in it, press your fingers inward…” We wait for the player to press the book button on the motion controller. When they do, we spawn the book in that hand in a shower of green magical glitter. Cawlin: “...and poof! There eet is! What an extraordinary book!” The book is turned to the first page, and as we look at it, some of the symbols transform into letters and words. RR: “Well -- I suppose, but again, what use is a book I can’t lose if I can’t read it?” Cawlin: “Well, It’s a magic book, and magic itself is composed of symbols or something like that -- don’t ask me, I’m just a stupid bird -- but I’m sure there’s some way you can figure out how to read those symbols? Yes? Let’s open eet and see what clues we can find!” The wizard opens the book, and on the very first page is a small set of instructions on its use, written in a poetic style: It’s an empty book It stores the spells a wizard learns It has a few left over runes from Sassafras Cawlin: “Oh, dear! The years just haven’t been kind to the pages of parchment. Even magic itself can’t protect its pages from the sands of time forever… Oh, no… oh, woe… it seems, knowledge… it has all been lost. Whatever will I do now?” RR: “Uh… you make less and less sense by the minute. You seem to know more than you’re letting on, so tell me bird, what do you know about magic and this book?” Cawlin: “Ehe. Well. ahem… Magic is just a tool used by mortals -- I mean, men… and eet can be used for evil or good. It just depends on the contents of the heart of the magician. Good magicians, naturally choose good magics, while evil magicians will choose… so called “evil” magics.” (Cawlin says “good” with disgust, and “evil” with affection) RR: “So what? How does that help us?” Cawlin: “One thing you must understand about magic, is that eet is composed of magical words and symbols. Without the proper words of a spell, there simply is no magic! So, men with the talent for magic, would often work very hard to find the proper symbols for magical spells. Sometimes, these… experiments, would go… very wrong! And they’d explode. Or turn into toads. Or become green for a day or two. Either way, playing with unknown magic is… dangerous.” Cawlin: “Once a good sequence of magical words have been found, the magicians would write them down in their spell books. Then, they could say the magic words at any time, and… POOF! The spell would just happen!” RR: “Just like that? It doesn’t sound so bad!” Cawlin: “Well, it’s not quite so easy… There are lots of symbols to choose from, and just as important as the symbol itself, is the color of the symbol! Without the right rrrrecipe, you might be using the right words but never actually working the magic.” RR: “So… magic words, magic orders, magic colors… why does it have to be so complicated?!” Cawlin: *chuckles* “heee heee hee, you’re barely even a novice. Of course it seems difficult for you now, but in the hands of a master magician, magic can be wielded to shape worlds...and… make fooooood. Like… delicious corn! Let us start there -- you haven’t had breakfast yet, have you?” RR: “I was just going to step out of the house to nibble on some delicious tree bark for breakfast…” Cawlin: “You -- with your talent for magic -- have been eating bark this whole time?! Unbelievable! It’s time to change that. Fortunately for you, and my oh, so generous mood this morning, I happen to have found a few symbols of magic.” RR: “What? You’ve been holding out on me. Why didn’t you say so sooner!” Cawlin: “Well, they won’t do you much good unless you know how to scribe them into a proper spell.” RR: “Where do I begin?” Cawlin: “First, we must go forage the forest for ingredients with magical properties. The first thing we’d like to collect, is a red pepper. Let’s go find some.” Rupert and Cawlin go wandering through the forest until they find a red pepper growing on a bush. Cawlin: “There! Right over there! A red pepper!” Rupert picks the red pepper. RR: “Okay, I’ve got the red pepper. Now what?” Cawlin: “The red pepper has the essense of red magic! That’s why it burns your mouth when you eat it. We must extract this magical essence and use it to write your first spell. Let’s go back home.” Rupert and Cawlin return to the mossy tower. Cawlin: “Everything has a bit of magic in eet. It is the job of the alchemist to extract this magic and brew bottles of magical extract. Many mortals don’t rrrrealize what they’re actually doing, but they treat these magical extracts as ‘medicines’, but it’s actually magic at work. A brewed potion has potency, depending on the skill of the alchemist and the ingredients used.” RR: “I’ve never brewed a potion. Where do I begin?” Cawlin: “Well, you don’t really have a prrrrroper alchemist work bench, so we’ll just have to use the most rrrrrrudimentary tools available to extract the magical essence from the red pepper. You must crush the red pepper between some rocks, and you’ll get a little bit of red magic essense. Try it now.” Rupert places the red pepper on a slab of rock and smashes it with a rock. A few seconds later, small vial of red liquid emerges. Cawlin: “You did it! A vial of red magic!” RR: “How do I use this?” Cawlin: “If you drank it, it would burn your mouth and upset your stomach, but we’re going to use it as ink to write magic symbols. Let’s go to your test chamber… Oh... you don’t have one. Well, that table will have to do then...” When Rupert approaches the table: Cawlin: “Fortunately, I happen to know two magical symbols -- ‘Li’ and ‘Tu’. We can write them down on a magical parchment, in any order and with any ink, and if the symbols match a spell, you’ll be able to save it in your magic book and cast it any time.” Cawlin: “To begin, grab a parchment and a quill!” Rupert performs a “use” action on parchment paper. The spell crafting UI pops up on parchment. Cawlin: “You’re barely even a novice, so you can only discover spells with two magical symbols. Later, you can cast much more complicated spells. Let’s begin with novice level magic.” Cawlin: “You don’t have a lot of parchment to work with, so you’ll need to find a spell quickly. To begin, select a symbol slot with your quill…” Rupert places his quill on a slot icon and a dialogue window pops up. Cawlin: “You only have a red magic essence, so choose that as your ink. Then, pick a symbol to write in this slot.” Rupert chooses a symbol (either “Tu” or “Li”) and writes it into the slot. After the symbol has been picked, it is written into the slot. Cawlin: “See? Even a novice can do this! Next symbol!” Rupert repeats the same process for the second symbol. RR: “Now, I’ve got two red symbols written down. Now what?” Cawlin: “Now, you try to cast these words! It’s already in your hand, so just give it a throw and see what happens…. I will just fly over here… and stay well out of the way...” Rupert throws the current magic spell. It either creates a magic spell (if correct), fizzles out, or creates a magical disaster. (Let’s assume it fizzles out) RR: “What? Nothing happened!” Cawlin: “You’re spell fizzled. Consider yourself lucky! That combination of symbols and ink was not a spell, let’s try again.” Rupert uses the parchment again. Cawlin: “This parchment is magical! As you can see, you got the right symbols and right color, but in the wrong order. Now, we can try a different sequence.” Rupert keeps trying out different symbols, until he writes out “Tu-Li” in red ink. When he gets this sequence: Cawlin: “You did it! You created your first spell! This is so exciting… I remember now! Tu-Li is fire, but your TuLi is very weak because you used a red ink with low magical potency. However, this spell is now saved in your spell book!” RR: “So, I can fling these little fire darts at any time now?” Cawlin: “Yes… you’ve begun the journey of a magician! You can find more symbols to discover other spells, and brew more potent potions to create stronger spells.” RR: “Wait a minute… my essence of red magic is gone! Did you steal it from me?!” Cawlin: “Relax yourself, Rupert! Whether you fail or discover a spell, the used ink is consumed. Magicians are always scavenging for ingredients to brew -- you magicians are scavengers, just like me!” RR: “Now what?” Cawlin: “Well, I must go. I smell a dead racoon down by the lake, and I’m absolutely starving. As for you? I saw an abandoned ruin this morning, but it was too dark and scary for me. Maybe your fire could shed some light on the situation? Or perhaps, you can find other ingredients?” RR: “You’re leaving me?!” Cawlin: “I’m getting rather...peckish. I’ll be back... Muahahaha!” Cawlin flies away and the wizard is left alone. There’s not much to do, other than hunt for ingredients or check out the abandoned ruin. At this point, we spawn clovers, blueberries, red peppers, orchids, and black lotus flowers. These are collectible ingredients which can be ground up and turned into vials. We also unlock the ancient ruins and make it accessible. Within the ruins is a new magic symbol which can be learned and a mortar and pestle. The player can summon a small flame to light their way through the darkness. There is a section of the ruin which is sealed off with a heavy door and some other strange symbols of magic. When the player emerges from the ancient ruin, the day has turned to evening. RR: “Wow, it’s evening already?” RR: “It’s getting late, I’d better get home before the forest monsters come out!” When it’s dark, we start playing large monster noises in the distant forest, mixed with snorting noises (like a sniffing pig), and something large crashing through undergrowth. RR: “There’s something out there… it’s hunting me!” Rupert returns to his wizard house. He’s tired and ready for bed. RR: “Whew, safely home at last. I need to get some sleep.” We wait for Rupert to go to sleep OR until it is 2AM in game time. Either way, we fade to black and we begin to hear snoring noises.
  18. 4 points
    For my persistent "dynamic" buffers I like to have a "CPUWritable" flag that lets you have two different behaviors. If that flag is set, the buffer is allocated out of an UPLOAD heap and can be written to directly by the CPU. To make sure that the CPU doesn't overwrite something that the GPU is reading, the buffer is internally double-buffered, and the buffers are swapped when the contents are changed by the CPU. With this set up you can only flip the buffer at most once per frame (where a "frame" is denoted by a fenced submission of multiple command lists to the DIRECT queue, followed by a Present), so I have an assert to track which frame the buffer was last updated. If the CPUWritable flag is false, then the contents have to be updated by writing to temporary UPLOAD memory first, and then copying that to the actual buffer memory in a DEFAULT heap. However I do it a little differently than you're proposing, since I use a COPY queue to do the copy instead of using a DIRECT queue. Doing it on the copy queue is trickier since you have multi-queue synchronization involved, but the upside is that the copy can potentially start earlier and run alongside other graphics work (which you usually want to do for initializing static resources). To again avoid writing something that the GPU is reading from, I also double-buffer in this case and only allow at most 1 update per frame. For the temporary memory from an UPLOAD heap that's used as a staging area, I have a ring buffer that tracks fences to know when it can move the start pointer forward. With your approach of doing the copy on the DIRECT queue, the nice part would be that it will be synchronized with the graphics work on the GPU timeline. This means that you don't need to double-buffer, or do any synchronization beyond your barriers. But the downside is that the copy will happen synchronously with your graphics work, instead of "hiding" in other work. You'll also have to track your fence on the DIRECT queue to know when to free your chunk from the UPLOAD heap. For choosing between whether to keep your buffer in UPLOAD memory or copy into DEFAULT memory, the best choice most likely depends on how you access the data. If the data is small and you're not going to do repeated random accesses to it, UPLOAD is probably fine (this covers a lot of constant buffers). If the data is larger and you access it multiple times, then it's probably worth copying it to DEFAULT so that you get full access speeds on the GPU (something like a StructuredBuffer full of lights for a forward+ renderer would probably fall into this category). Anyway, I just wanted to share what I'm doing to give you a few ideas. I'm not claiming to have the best possible approaches here, so feel free to do what works best for you and your engine. EDIT: I forgot to add some links to my code for reference. You can find the buffer code here, and the upload queue code here. Just be aware that the descriptor management is a bit complicated since that code uses persistent bindless descriptor indices, so there's some jumping through hoops to make sure that the descriptor index doesn't have to change when the buffer is updated.
  19. 4 points
    At a AAA studio, if they're using a custom / in-house engine, it will likely be just as big and complex as Unreal... If you get a job at a place like that, you'll still be making games on top of a massive engine. Even if you get a job there as an engine developer, it will be much closer to fiddling with the UE4 code-base, than your student-home-made-engine codebase. So, showing that you can actually work with a big, bloated, over-engineered game making toolset is kind of important. Doing fancy tech stuff from scratch is also important, if you want to work in a very technical role... but making a custom renderer from scratch when you're applying for a gameplay role isn't the best use of your time. In that case, a gameplay system built on an existing engine would be a better portfolio piece.
  20. 4 points
    Forgive the flippant response, but if you make an MMORPG single-player, aren't just left with an RPG? There are literally hundreds of great single-player RPGs. If none of those are to your taste, you'll have to be a little more specific about what elements of the MMORPG genre you think aren't sufficiently represented in single-player RPGs.
  21. 4 points
    Just because UE4 does it, doesn't mean that it's correct. They can still be trampling all over the rules of OO. Big products made by 100's of programmers are often more likely to do so If your entire code base is designed around the idea of extending classes, then yeah, you get pushed into extending classes in order to add new features to that existing code base. If your code base is designed around the idea of composing new objects from other objects, then you get pushed into writing new composite classes in order to add new features to that code base. Inheritance is only "the only way" if the code is forcing that particular "solution" upon you. Good uses of inheritance are pretty rare...
  22. 4 points
    DoD and OOD are not opposites. They're orthogonal. You can do both. e.g. this presentation could be seen as giving OO a knock-out punch, but it's actually about how to take an OO design and implement it using DoD thought processes instead of "typical" C++ thought processes. OO has specific code features, such as classes, and special syntax to go with that. DoD is a process in how you think about your code; it doesn't have any specific syntactical features or new coding paradigms like classes. for each render component as renderable if the render components are individually allocated with new, this iteration will randomly jump all over memory. You're likely to incur a cache miss on every single iteration. transform = renderable->m_entity->m_transform the contents of the renderable won't be in cache, the contents of it's parent entity won't be in cache, and the contents of that entity's transform won't be in cache. This loop hardly does any work. This loop does an extraordinary amount of nothing -- just waiting on RAM->Cache requests to complete -- and also does little bits of sporadic work. It is the opposite of DoD thinking. If you're actually interested in DoD, find out: What is the exact, minimal set of data required to fulfil the Transform::set_draw_data and Renderable::Draw functions. How can I structure that data set to be as small and compact as possible. How can I generate this data set ahead of time in an efficient way. Then that has a knock-on effect to the systems that generate the data -- how can you restructure their data to support your new goals? How can you restructure all the code that interacts with their data? But, for now, I would probably just forget all about DoD and just focus on making something work, rather than trying to make something fast. DoD requires an examination of the specific details of a specific problem. You can't just apply a general pattern to every problem -- that's the opposite of DoD (e.g. The ECS pattern boils down to "just use a table for everything", which is pushing one solution regardless of the problem is -- so blindly following ECS is not DoD). In some situations, sure, adding extra steps may just be moving problems around with no purpose. In other situations, a multi-pass solution may be the best solution -- e.g. outputting a list of indices into a data set in the first pass, and then collecting the data items associated with those indices in a second pass. It all depends on the specific problems that you're solving. Note that polymorphism is quite often the opposite of DoD though -- as virtual functions mean "I don't know what code or data is going to execute / be read or written now".... and if you don't know what your program is about to do, that's about the least specific you can possibly be!
  23. 4 points
    Yes. I did a breakdown for you. By looking at the video we can see there are 5 points where the images are changing. That is why the last image looks so wrong. The character is made of: Head image, Body image, BackPack image, Left arm image, Right arm image, Left leg image, Right leg image. There also is a animated band but it is just attached to the head. The objects are drawn from a top down view so that little change is needed to each. Mostly looks like the artist was using a perspective tool and filling in details. The arms and legs are just rotated. The Head, body and backpack changes. The arms and legs remain the same but are mostly hidden. Hope this helps.
  24. 4 points
    Hi everyone, I know there is a lot of blogs and advice about what to do and not do for a beginner in a game industry, I even read a lot myself to find inspiration and avoid common mistakes. Unfortunately, there is not so many talking about real experiences. I am here to tell the story behind "Soul of Mask", my first game and I hope not my last. I will avoid a long post, so it will be in different blog entries presented like this: - Origins and first difficulties, - Technical: Game engines, programing language, tools - Marketing and conclusion. In all point I'll talk from the beginning to the end of the project, there is no chronology so you are free to read what you want in the order you want. Let start then... My name is Alain Perrin, as you may have noticed, not a native English speaker. I am a system dev in a Chinese company based in China. So yes I live in China for quite many years. I always wanted to create a game but I always stop writing my game as soon as I was satisfied with the technical problem I solved. It was enough for me until my wife (fiance at that time) talked about people proud of themselves without any real achievement. Yes, she didn't realize it but it hit me right in the brain and let say ego as she was not talking about me. "Yes I think I can do a game but I never proved it". It is where I decide to start a game and finish it to prove to myself that I can really do it. This will explain a lot of choices I made for my tools such as Programming languages and game engines. Now we know I never planned to make a commercial game, it was just about to start something bigger than Tetris (I did finish it around 2003, a mixt of ASM and C with class dirty code). I decide Pacman with a lot of improvement in the ghosts. My major was AI and face recognition and I wanted to make Pacman with clever ghosts. But, with time I started to add more and more stuff and the game didn't look like Pacman at all, at least in the gameplay. It was still a mase game but a lot of things were too far from Pacman it is when I decide to stop and think about something else, a real game. I started to look for help; another developer and at least a drawer could be pixel artist or just 2D designer even a comics drawer. It is also when the first problems came. As a developer finding another developer was easy to keep him on the project was another challenge. So you guess, he left. And this brilliant guy leaving was a hard strike to my moral, it was so demoralizing. However, this guy was totally honest and told me: " I am leaving because I don't see where this will go". At first, I thought he was talking about money, he may think this project will not bring any money at all. If it was the case I had no way to convince him to stay. But he was talking about achievement. money is not so important when you do something you want to, money is a reward I would love to sell 1Million copy of "Soul of Mask " but it was not my priority and we shared the same thoughts. The problems were the fact that he didn't believe it will finish one day and didn't want to waste is time. Now another part of my personality took control of my mind over depression. The love of challenge. Now I have a new challenge, everything I need to go back to work. I restarted everything with a better design as now I knew I was not doing Pacman anymore. It is also at that moment I made my first big mistake. I read after that it is a common one " I do all the code and I will find soon or later a graphist". So one year passed when I started "Element mask" and I had this: Element Mask Element mask was supposed to be the full game. It was the story of a young man who has to collect all the masked stollen by demons. It was not so beautiful but I was sure that with a full gameplay and a story I will find someone to draw. I google images and made something different. all images in the following image are downloaded from google image: Here you can on the right bottom your different special power. So I spent almost another year trying to find someone to draw. I contacted my brother in law in France who agreed to help. then I went there, meet him and he realised that is was not 3D game and he could not make 2D graphics assets. So 2 years passed, I have an almost ready gameplay but no graphics. My Brother in law and one of his friend remembered that they have a co-worker that may help. This happened in August 2016. They contact the guy who said OK to meet me the next day. My designer invited me to his place and I was already in love and impressed, this guy is a gamer. He had everything, a lot of games and objects from games of all time. Obviously, if I can convince him then that will be finished. And I did it, he was in. I left France and move back to China, He sent me Emails to show his interest. I let him free to change what he wants in the game as long as I can program it. and he did bring the idea of half mechanic characters. here is his first sketch: Hey guys, honestly it was promising, right? But if you bought "Soul of Mask" today you already guess that it didn't work. How? I don't know myself. This was his last email. After that he disappeared, no news, no answers nada, nothing, keine, rien. As if it was not enough I injured myself playing football (soccer for USA). ACL was torn, for those who play sport they know it is a serious injury. Good can come from Bad. Nine months without sport said the doctor, and at least 2 weeks without moving my right knew. So I had to stay at home and this was the good part. I use to play football 3 times per week plus 2 times of basketball. For almost a year I will have to do something else. Unfortunatly I still had no news from my designer. I decided to go again to France to visit my family and try to contact him again. I did and he said sorry but he didn't have time to work on Element mask. Angry programmer. That was too much. I was very pissed. I nicely said " ok I understand we all have our job and our life. No problem". But inside all was fire ready to burn everything around. August 2016 to February 2017 you cannot find 15 seconds to send me a WhatsApp to tell me you are out of the project? you are busy but me I can just wait and hope? I realized that everything is really relative. I was convinced of total failure if I attempt to make Element Mask alone but I just have the proof of the opposite: I would have to work alone if I want it to finish one day. I just remember a funny fact, I can draw myself. I used to draw comics for my classmate when I was in middle school. I bought my watcom and started again. My level is far from what I could do but it was enough for buyer to accept it. actually no body said my game was ugly: Rip Element mask My problem now was different. I had nobody to wait but I was not fast to draw as I was before. Worse, I cannot draw what my code is made fore. So gameplay changed a lot. Every time I failed to draw something, the gameplay will change. This is for example how I moved from a character wearing a mask to bouncing masks. Soul of Mask was born. It was something I could finish before the end of 2017 and I did it. I learn a lot about people, life and myself in this adventure. next blog entry will talk about the coding part. thanks for reading.
  25. 4 points
    Here is my submission for the challenge. Sadly I don't have the time to work on it again before the end of the month, and the AI is stupid to say the least. The twist is pretty straightforward, the arena is round instead of rectangular. When a player hits the ball it changes its color. When the ball is red if it exit the arena the point will go to the red paddle. Viceversa when it's blue the point will go to the blue paddle. The two paddles can also overlap and both hit the ball. When this happens and the ball exit the arena a point will be subtracted to both player. Here's the blog post: I hope you like it Code reviews are really appreciated! Round Pong.zip Solution.zip
  26. 4 points
    * Moderator hat on* This is a gentle reminder that we are in the For Beginners forum, discussing a project being implemented by a beginner asking for help with is code. Discussion on the poorly-defined meanings of object oriented-ness are not appropriate. Discussions in For Beginners should be focused on the actual problem the beginner is having. * Moderator hat off* Now, on to the updated code. I think that code is much more readable, even though it takes up more lines. Hopefully you agree, as it is your code and you're the one who gets to live with it. If I use the code-collapse feature of my IDE, the code is broken up into easily understood blocks: main(), Initialize(), Move_ball(), AI_Movement(), Player2_Movement(), and Reset_all(). I can look at that and understand your game. Expanding any one of those gives me logic that I can easily understand. For example Player2_Movement() opens to keypressed up and keypressed down. Each of those actions is easily understood when I expand them. Those are good, especially in beginner code. If I were looking to improve it -- even though what you've got in there looks like a runnable game -- I would next try to simplify by merging duplicate functionality. Moving up and moving down seem like the same operation, the only difference is that one is positive and the other negative, you can use a clamp function to limit movement both at the top and the bottom. That's 7 lines removed. The AI has different logic controlling if they move the paddle up or down, but the actual logic of moving of a paddle is the same as you're only modifying the y value. Extract the duplicate paddle-moving logic to a new function that accepts both a reference to a paddle and the direction it moves, and you remove another 10 or so lines of duplication. Moving the ball also has a lot of duplicate math that depends on ballsp_x is positive or negative. That duplicate math can probably also be merged. I'd also look at more consistent naming conventions. Sometimes they start with uppercase or lowercase, sometimes they have underscores, sometimes they have abbreviations. There are automated ways to rename all variable instances in most IDEs, so it is usually an easy thing to clean up. Games are shipped but never really done. There are always improvements developers want to see and bugs that could be fixed. Players don't normally dig through the source code, and if they did often they'd encounter nightmare fuel. If your code does the things you want to do and fits whatever performance criteria you've been given, you can call it good enough, even when it could be better.
  27. 4 points
    In order to see how quickly the value decreases with distance, I divided the value at 10 by the value at 20, and their ratio was exactly 8. So if a factor of 2 increase in distance results in a factor of 8 reduction in the value, it suggests a dependence with 1/(x*x*x). 12800.0 came from fitting a single point at distance 10. Then I saw all the other points match exactly.
  28. 4 points
    I have had difficulties recently with the Marching Cubes algorithm, mainly because the principal source of information on the subject was kinda vague and incomplete to me. I need a lot of precision to understand something complicated Anyhow, after a lot of struggles, I have been able to code in Java a less hardcoded program than the given source because who doesn't like the cuteness of Java compared to the mean looking C++? Oh and by hardcoding, I mean something like this : cubeindex = 0; if (grid.val[0] < isolevel) cubeindex |= 1; if (grid.val[1] < isolevel) cubeindex |= 2; if (grid.val[2] < isolevel) cubeindex |= 4; if (grid.val[3] < isolevel) cubeindex |= 8; if (grid.val[4] < isolevel) cubeindex |= 16; if (grid.val[5] < isolevel) cubeindex |= 32; if (grid.val[6] < isolevel) cubeindex |= 64; if (grid.val[7] < isolevel) cubeindex |= 128; By no mean I am saying that my code is better or more performant. It's actually ugly. However, I absolutely loathe hardcoding. Here's the result with a scalar field generated using the coherent noise library joise :
  29. 4 points
    Are you sure this matches in your code? You need to store pointers to the objects rather than the base objects themselves. The way the language usually enforces this is for your code make the base class abstract so it cannot be instantiated. They are commonly called an ABC, or Abstract Base Class, because of this. Except in rare cases, only the endmost leaf classes should be concrete, everything below it in the hierarchy should be abstract. In that case, are you certain you are following LSP? Are the sub-objects TRULY able to be substituted for each other? Code should be able to move back up the hierarchy to base class pointers, but should never need to move back out the hierarchy, instead using functions in the interface to do whatever work needs to be done. As a code example: for( BaseThing* theThing : AllTheThings ) { theThing->DoStuff(); } versus: for( BaseThing* theThing : AllTheThings ) { // Might also be a dynamic cast, or RTTI ID, or similar auto thingType = theThing->GetType(); if( thingType == ThingType.Wizard ) { theThing->DoWizardStuff(); } else if( thingType == ThingType.Warrior ) { theThing->DoWarriorStuff(); } else ... ... // Variations for each type of thing } Also, in general it is a bad idea to have public virtual function. Here is some reading on that by one of the most expert among C++ experts. This is different from languages like Java where interface types are created through a virtual public interface. Some people who jump between languages forget this important detail. As the code grows those public virtual functions end up causing breakages as people implement non-substitutable code in leaf classes, as it appears you have done here.
  30. 3 points
    Hi there, I really like the idea of a fog-based enemy but I think that the combination of fog (limited view for the player) and this could result in excessive difficulty (unless you want this) because you are enhancing the enemy's abilities while weakening the player's. Personally, I think it'd be interesting to use the fog as a "hiding" mechanism for the enemy. For example, It could use it if its health drops and take advantage of the limited visual capabilities of the player to regain health. Player-side this results in a situation where you are "weakened" (low visual) but you have the possibility to find the enemy while it is regaining health and possibly deal lots of damage (high difficulty, high reward if you find it).
  31. 3 points
    I believe it would be easier to get a job outside of gamedev with a cs degree, a lot easier then trying to get a job outside with a gamedev degree. A lot of the stuff you learn there aren't useful in many other areas, they are more a specified part of the field. GameDev is an happy dream for many, but does not result in a happy reality for even more. Better to have a job and a hobby, than 'nothing'. So for job security and your future, I'd go with computer science.
  32. 3 points
    The X86 family incurs a penalty for doing it, and only the really old types support it. The 64-bit and larger data types typically require proper alignment. C++ is supposed to properly align the values for types supported by the compiler. For tracking it down, usually this comes from improper casts. A common source of those casts is serialization. It can also happen anywhere else you perform unsafe casts, like a reinterpret_cast to convert from one type to another that has stricter alignment requirements. When loading values from disk or network you cannot blindly cast to the right data type or data structure. You need to get the address of a proper variable, then copy the bytes directly into that object. Usually that is done with bitwise manipulations or memcpy(). Once the data is loaded into properly aligned values, C++ should manipulate the data exactly as expected. It adds a performance penalty (if it works at all on the compiler). The compiler adds additional code to ensure the value is suitably aligned, sometimes using temporary objects for member access.
  33. 3 points
    I typically have component handles act less like stand-alone pointers and more like indices (which require some external knowledge of the container being indexed). Often if one system of components is referencing another system of components, it can have a pointer to the other system, while the components simply hold index-like handles (instead of pointer-like handles). The system can dereference a component's index-like-handle by combining it with it's own pointer. To catch programming errors, in debug builds, my index-like handles contain an index and a pointer/ID as well, so that the dereference process can be validated (is this handle being used to index the correct container?). Off topic: In this example, that just forces C1/C2/C3 to contain a vtable for absolutely no reason at all. Firstly, inheritance is a code smell, and secondly, A is not being used as an interface for ownership (there's no calls to delete with an A* argument). This feels vaguely like a violation of OO's LSP rule to me for some reason (any algorithm that works on a base type must also work on a derived type).... But yes, Handle<B> could contain a pointer to the std::vector as well as the index into it... This gets complicated beecause the vectors are of different types. One (probably heavy-handed) solution off the top of my head would be for Handle<B> to contain an accessor function like: std::function<B*()> getter = [&c2s, c2index]() { return &c2s[c2index]; } Alternatively, Handle<B> still just contains an index and a templated getter function: template<> struct Handle<B> { int index; template<class T> B& Dereference(std::vector<T>& vec) const { return vec[index]; } } And as above, in debug builds I would store extra data inside the handle to validate that the correct vector is being passed into the Dereference function.
  34. 3 points
    1. Get the vision out of your head and into a document. Anything you won't compromise on needs to be in the document. This document is to be visible to new team members, so that they know exactly what is expected when they join. 2. With the above in mind you need to more carefully vet everyone who joins the team. Ask what their motivation is, and make sure it fits with the project. Make sure you are able to offer what it is that they need to feel that their time is being spent in a worthwhile way, and if that can't be done, don't bring them onto the project. You can't pay them in money so you need to be able to pay them in some other way - e.g. the ability to express certain ideas. But make sure that is compatible with your needs. 3. Accept the fact that some people will leave. They won't like the idea that they do a lot of hard work but you get to make the decisions. Many will want more control over the project than you feel you can offer. That's their right to want it. You can't change it. Just accept, up-front, that there's no one weird trick to compel someone to stay on your project doing your bidding.
  35. 3 points
    Yep, that's right, and no it doesn't need to be unmapped.
  36. 3 points
    We have a work-stealing task scheduler that spawns 1 thread for every core on the CPU (minus 1 for the main thread). Then we create a bunch of tasks for groups of draw calls, and throw them a the task scheduler. We've tried both 1 thread per logical core (Intel CPU's with hyperthreading have 2 logical cores for every physical core) as well as 1 thread per physical core, and we've generally found that trying to run our task scheduler thread on both logical cores to be somewhat counterproductive. But your mileage may vary. AMD has some code here that can show you how to query the relevant CPU information, Writing your own task scheduler can be quite a bit of work (especially fixing all of the bugs!), but it can also be very educational. There's a pretty good series of articles here that can get you started. There's also third-party libraries like Intel's Thread Building Blocks (which is very comprehensive, but also a bit complex and very heavyweight), or Doug Bink's enkiTS (which is simple and lightweight, but doesn't have fancier high-level features). Windows also has a built-in thead pool API, but I've never used it myself so I can't really vouch for its effectiveness in a game engine scenario. My general advice for starting on multithreading programming is to carefully plan out which data will be touched by each separate task. IMO the easiest (and fastest!) way to have multiple threads work effectively is to make sure that they never touch the same data, or at least do so as infrequently as possible. If you have lots of shared things it can messy, slow, and error-prone very quickly if you have to manually wrap things in critical sections. Also keep in mind that *reading* data from multiple threads is generally fine, and it's *writing* to the same data that usually gets you in trouble. So it can help to figure out exactly which data is immutable during a particular phase of execution, and perhaps also enforce that through judicious use of the "const" keyword.
  37. 3 points
    Number of triangles is irrelevant to the CPU - how many draw calls do you have? If it's thousands, you may get some benefit from using multiple threads to record the draw commands. In my experience, with less than around a thousand draws, there's not much benefit in threaded draw submission. Most engines these days make a pool of one thread per CPU core, and then split all of their workloads up amongst that pool. So on a quad core, I'd use a max of 4 threads, and as above, also no more than around (draws/1000)+1 threads.
  38. 3 points
    What you want to do is beyond what any games currently do. The Total War games work with far fewer units and they almost certainly perform hacks to simplify their logic. I will add this: your grid is too small to give you much benefit and I expect the cache coherence is almost zero with rows that long. A more complex spatial database - perhaps even just a large grid of smaller grids - may give you significantly faster lookups much of the time, if it means that the 8 grid squares you're examining are almost always in the same cache line. But what you gain there, you might lose on having the 2 stage lookup, or on having to occasionally search across multiple large grid squares.
  39. 3 points
    Hi All! I thought it was about time to become more actively engaged in the site and share my aspirations. First off, let me say that I am a senior citizen (I first learned to program using BASIC on a teletype machine using a time-share system at college [I went to Dartmouth and my intro Calculus class was taught by John Kemeny]). I got into game design/development as a hobby after playing around with making websites. I work full-time as a government contractor and have been for the past 13 years. My work hours and work environment has not really allowed me to get too deeply involved in the process. Much of my time has been spent reading about game development; playing around with recommended software (and their tutorials); and having fun in the process with my new hobby. However i am now looking at retiring from full-time work and spending my retirement time making games. Nothing fancy or ambitious, but maybe something that will provide a supplement to my pension. As a start I have taken a more serious approach to making games. I've browsed this forum and noted a lot of advice from vets and I appreciate you taking your time to help us noobs. I will be doing everything myself, so I guess that categorizes me as a solo indie developer. In that respect, any advice for someone like me will be appreciated. Thanks for reading.
  40. 3 points
    Try out TDD, but beware that it has a larger learning curve than it initially seems to. You will most likely do things in a cumbersome way for a while as you get used to it, and you'll most likely shoot yourself in the foot a few times with it like I have. Try to avoid dependency injection frameworks. They're just one more thing that can go wrong. It's likely that you will be able to use TDD in a way that does not require dependency injection frameworks at all. If you get to the point where you're methodically using TDD style you will be building your program bottom-up and can avoid unwanted coupling from the start. Make things simple. Single responsibility principle is extremely important. Don't try to make everything an interface to appease the mythical DI gods; usually one function that does exactly what you want to do is the only one that ever needs to fulfill that interface. For Unity, attempt to write as much of your code as possible OUTSIDE of MonoBehaviours. MonoBehaviours have unwanted dependencies and horrid initialization restrictions compared to plain old C# classes. It's easier to test code if it doesn't require MonoBehaviour/GameObject baggage.
  41. 3 points
    As far as I can tell, it batches up a handful of C++ files, then generates code for that batch all at once. But the batch size is limited, so you see more Generating Code the larger the project is. Nothing's going wrong.
  42. 3 points
    There are just too many options. This forum is primarily about game AI. A few big areas (off the top of my head): Locomotion (pathfinding, flocking behaviors, animation controllers) Full-information two-player games (chess, checkers, go) General game playing Tools for game designers to describe behaviors (behavior trees, goal-based architectures, planners, utility systems) Machine learning (reinforcement learning for driving games, AlphaGo) Dialog (select phrases appropriate for the situation) Automatic adjustment of difficulty levels to give the player a good challenge I am probably missing some big ones, but perhaps something in that list piques your interest.
  43. 3 points
    For general code structure, since you're still learning, don't try to get too complex. Do the simplest thing that you think might work, and only make it more complex if you need to. For a turn based game, the simplest things you NEED are a way to keep track of whose turn it is (one variable?), having a way to perform some action(s) during a turn (something which gets input from a player or an NPC), and how/when to go to the next turn. The main suggestion I have for any new programmer is: Try to keep every function very short and simple. If you need to make something complicated, split it up into simpler parts. Turn each simple part into a function, then you can make your more complicated function by just calling the simple ones. There is a tendency to do the same kinds of things in multiple places in a game; you should try to make simple functions so that you can reuse it instead of copy-and-pasting the same code in multiple places. Always make sure to test your code frequently! Even experts make silly mistakes and it's best to catch them early. You can also automate this testing process. If you want to jump right in, look up: "Unit testing" (Unity has built-in support for these as well!) and "Test Driven Development". This stuff is somewhat separate from C#, kind of like how knowing how to use a debugger is separate. Just like knowing how to use a debugger, knowing how to use unit testing can make profound improvements to your development experience.
  44. 3 points
    32-bit floating point numbers, called "float" in C, C++, C#, and various other languages, can accurately represent 23 bits of precision, plus another bit for sign. So they should work with any number from +/- 2^23, or about 8.38 million to -8.38 million. Converting from base ten to floating point and back to base ten is only guaranteed for 6 decimal digits precision, although it should work up to that range of 8.38. Beyond that it cannot fit exactly within those 23 bits. That conversion applies just as much to 7654321 as it does to 0.007654321 or 765432100000000. As for the range, there is a must-read article, "What Every Computer Scientist Should Know About Floating-Point Arithmetic" which explains how it works, why it works, how certain calculations are troublesome, catastrophic cancellation where your result is garbage, and more. It requires a bit of math to understand, but it allows you to be far more precise in how much error you've accumulated from various sources, instead of the handwaving answer like "just check within 0.001 or something".
  45. 3 points
    That is one of the most difficult balancing acts within the business of games. There are some highly vocal, high profile people who will complain about the existence of microtransactions. There are some highly vocal, high profile people who will decry any game that requires people to spend time on games, that everything should be unlocked and available instantly. There are highly vocal, high profile people who will decry any games that use a progression system or story mode to advance, that anything requiring effort by the player is actually grinding and should be removed. There are highly vocal, high profile people who will shout to the world how whenever a player must pay for a game it is extortion. There are highly vocal, high profile people who tell others that the games are a great value. No matter what the company does there are highly vocal, high profile people who will shout it down. The tricky part is to balance them out. You want enough people giving positive feedback and actually paying for the game, but you also want a portion of the people to be offended because otherwise you won't make money and will go out of business. It further hurts the entire industry that many communities are highly toxic, where threats of felony crimes against the developers are commonplace and even encouraged. I've had co-workers get death threats before, including some where FBI agents came to talk to everybody after finding the death threats to their family members were actually credible threats. There are also other developers, even a few amazing indie developers, who have left the industry due to the highly toxic players and repeated threats from so-called fans. There is nothing "just learn how" about it. No matter what developers and publishers do there are people who will be deeply offended and will publish it all over the Internet. A good balancing point is incredibly difficult to find.
  46. 3 points
    Non-free mobile games don't sell. It's either micro transactions or advertising, or both in that part of the industry. Preferably both in a way that meshes with the game design and doesn't piss off the players. Note that when run as a business, a successful model *will* piss off the perfect percentage of players. Pissing off players loses you money, but obnoxious micro transactions makes you money. The balance is in the middle where you monetise the crap out of it and piss off some people, but not too many. The best way to make money isn't going to be pretty. You can ask individual people to be nice and not try to make the most money possible, but you can't ask a publicly traded corporation not to to that! Pay to win micro transactions in a full priced PC game is always going to piss off your players, and IMHO will completely undermine your gameplay too. I actually don't know how EA thought this would work... Cosmetic micro transactions are pretty much forgiveable in any game though...
  47. 3 points
    Most competetive RTSes end in "gg" and one team surrendering rather than playing until every single building is dead. That's the gaming equivalent of this. Whether this happens for an entire match (ala StarCraft) or if there is a higher level 'campaign' or 'war' layer wrapped on top of it doesn't matter.
  48. 3 points
    Hi! We are Evil Corporation Games, an indie studio, which was founded in 2016. In April 2017 our first game project - Star Story: The Horizon Escape (a text turn-based adventure RPG with 24+ alternative endings) was released on Steam. We are currently working on our next game - TERRORHYTHM. That will be rhythm + beat'em up action in the style of cyberpunk. In this blog we will inform you about our game projects and the latest news about it. First post we would like to dedicate to our first project call "Star Story: The Horizon Escape". It was released on Steam 05.09.2017 (http://store.steampowered.com/app/610310/), then it was published on itch.io, g2a.com and gamersgate.com. Was a work experience with chrono.gg. Soon Star Story will be available on kinguin.net and greenmangaming.com also. It’s a text turn-based adventure game with elements of RPG. The plot is developing in accordance with the actions of the player; there are 24+ alternative endings of an exciting adventure. Trailer: A spaceship of archeologist Van Click crashes, and he finds himself on the last unexplored planet in the whole galaxy called “Horizon”. As the Hero is trying to get out from this planet, he meets various inhabitants of unknown locations; he has to struggle for life encountering extremely aggressive species of Fauna and resolving various puzzles. The end of this eventful flee from the Horizon planet depends only on the player’ choice. In this game we have mixed the mechanics of dialogues, choices, turn-based battles, puzzles, crafting and technology researches. Work on this game lasted 1 year. And before an official release Star Story took the first prize in the nomination «Best PC game» according to Indie Cup 2017 and got the first place in the Deconstruction Workshop at the White Nights St. Petersburg 2017 conference. As it our first post, in honor of it we would like to share 5 STEAM keys to Star Story for our very first readers and friends here: FZGMK-9HVVZ-R6HY4 6RYY4-VBX2Z-67X2B 3VGHH-Q8YY9-LTW73 J4CRJ-ZAZFT-X8FIV HG8RV-IQ8Y4-IEH8A Very soon we will post the early details of our new project making, that will be released Spring 2018.
  49. 3 points
    Wow... a lot of facepalm here. I can't see how you would need to do "research" on a topic that 30 minutes worth of Googling would solve for you. Dijkstra is uninformed and therefore kind of wandery. A* is informed with a heuristic and therefore more directed. It is also guaranteed to find you the shortest path if a path exists provided an admissible heuristic. It also supports arbitrary geometry shapes such as navmesh polys so you don't have to be entirely grid based. You can also arbitrarily change the edge costs between polys to represent something other than distance -- for example terrain type -- so you can bias the results easily to match the world. There are plenty of optimizations as long as the environment fits. e.g. if you are grid based, you can use things like JPS (Jump Point Search) and JPS+. Trying to do a survey and "research" on this is like polling the Math and Physics forum to see what the best way to find the area of a circle is.
  50. 3 points
    Particles might number in the millions, but we don't try to send them across the network. The amount of objects you can send is proportional to the amount of data each one needs. Sorry for such a flippant answer but there's no trick or magic here. You can send as much data as your network bandwidth allows (nothing much to do with packet size, incidentally) and the less data you need per entity, and the less frequently you want to update them, the more entities you can update. To get transmission sizes down, you need to think in terms of information, not in terms of data. You're not trying to copy memory locations across the wire, you're trying to send whatever information is necessary so that the recipient can reconstruct the information you have locally. e.g. If I want to send the Bible or the Koran to another computer, that's hundreds of thousands of letters I need to transmit. But if that computer knows in advance that I will be sending either the Bible or the Koran, it can pre-store copies of those locally and I only have to transmit a single bit to tell it which one to use, as there are only 2 possible values of interest here. Similarly, if I want to send a value that has 8 possible values - i.e. the directions we talked about - that's just 3 bits. I could pack 2 such directions into a single byte, and leave 2 bits spare. Or I could send 8 directions and pack them into 3 bytes (3 bytes at 8 bits per byte is 24 bits to play with). If you're not comfortable with bitpacking, maybe read this: https://gafferongames.com/post/reading_and_writing_packets/