tag:blogger.com,1999:blog-32571179170712629142024-03-19T02:33:15.792-07:00Cyclone Game Engine DevelopmentSteel Cyclone Studios' Game Engine BlogJordon McClainhttp://www.blogger.com/profile/18342097908172252205noreply@blogger.comBlogger92125tag:blogger.com,1999:blog-3257117917071262914.post-5374938603435976182023-09-26T14:21:00.004-07:002023-09-26T14:26:54.957-07:0092.) MonoGame, FNA & Godot Triumph due to Unity's New Pricing Model<div style="text-align: center;"><iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/PR68iEOO2Bg?si=itn5QVI61JKBvqAa" title="YouTube video player" width="560"></iframe></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: left;"><div> MonoGame, Godot, and FNA (FNA Framework) are game development frameworks and engines that can potentially benefit from Unity's new pricing model in various ways:</div><div><br /></div><div><b><span style="color: #93c47d;">1. Cost Savings<br /></span> </b>Unity's new pricing model, which charges developers based on the number of installations and revenue thresholds, can be quite expensive for larger game development studios or projects with a high number of installations. Monogame, Godot, and FNA are open-source or free-to-use alternatives, which can significantly reduce development costs, especially for indie developers or smaller studios.</div><div><br /><br /></div><div><b><span style="color: #93c47d;">2. No Revenue Share</span></b> <br /> Unity's new pricing model includes a revenue share component, where developers pay Unity a percentage of their earnings once they reach a certain revenue threshold. Monogame, Godot, and FNA do not impose revenue-sharing requirements. Developers can keep all of their earnings, which can be a significant advantage for those who want to maximize their profits.</div><div><br /><br /></div><div><b><span style="color: #93c47d;">3. Transparency</span></b></div><div> Unity's changes in pricing structure have caused concerns about transparency and how the company tracks and defines "valid" installations. Monogame, Godot, and FNA, being open-source projects, offer transparency in how they work and do not impose hidden fees or ambiguous metrics. Developers using these engines have more control and visibility into their game's development and monetization processes.</div><div><br /><br /></div><div><span style="color: #93c47d;"><b>4. Customization<br /></b></span><b> </b>Monogame, Godot, and FNA provide more flexibility and customization options compared to Unity's more closed ecosystem. Developers can tailor their games to their specific needs without being restricted by Unity's pricing tiers or policies. This can be especially advantageous for developers with unique or complex game development requirements.</div><div><br /><br /></div><div><b><span style="color: #93c47d;">5. Community and Support</span></b></div><div><b> </b>While Unity has a large and active community, Monogame, Godot, and FNA communities are also thriving and supportive. Developers can seek assistance, share knowledge, and collaborate within these communities, often without the need for expensive Unity support services.</div><div><br /><br /></div><div><b><span style="color: #93c47d;">6. Cross-Platform Development</span></b></div><div><b> </b>All three alternatives (Monogame, Godot, and FNA) support cross-platform game development, allowing developers to target multiple platforms, including Windows, macOS, Linux, iOS, Android, and more. This versatility can be beneficial for developers looking to reach a broad audience without the constraints of Unity's pricing model.</div><div><br /><br /></div><div><b><span style="color: #93c47d;">7. Licensing</span></b></div><div><b> </b>Monogame, Godot, and FNA typically use permissive open-source licenses, which means developers have more freedom to use, modify, and distribute these engines without worrying about licensing fees or restrictions. Unity's licensing terms, on the other hand, may have limitations that affect certain types of projects or businesses.</div><div><br /></div><div> In summary, Monogame, Godot, and FNA can benefit from Unity's new pricing model by offering cost savings, transparency, customization, and community support. These engines provide alternatives for developers who want more control over their development process, don't want to share revenue, or seek flexibility in their game development endeavors. Ultimately, the choice between Unity and these alternatives depends on the specific needs and preferences of the individual developer or development team.</div><div><br /></div></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/lFuM-EWj9IY?si=Y5tQfKWVCCWPjbJX" title="YouTube video player" width="560"></iframe></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /><div style="text-align: left;"><div> The gaming world is buzzing! Unity's New Pricing Model Sparks Rebellion Among Game Developers with controversy as Unity, a prominent game development platform, faces a revolt from a collective of 19 companies mainly based in Europe, and primarily focused on mobile game development. These developers have come together to issue an open letter demanding that Unity reevaluate its recently announced pricing model changes. This dramatic action taken by developers, representing thousands of games with billions of downloads, includes suspending all IronSource and Unity Ads monetization in their projects until Unity reconsiders its new pricing structure.</div><div><br /></div><div><br /></div><div><b><span style="color: #6fa8dc;">The Unity Saga</span></b></div><div> Unity has found itself in a heated battle with its users, and the situation is escalating rapidly. What has triggered this uprising is Unity's decision to overhaul its pricing structure, shifting towards charging developers for each installation of a Unity game after specific download and revenue thresholds are met. While Unity asserts that only a small fraction, approximately 10 percent, of its user base will be affected, the lack of clarity regarding how Unity plans to track installations and distinguish between "valid" and "invalid" ones has left developers in a state of uncertainty.</div><div><br /></div><div><br /></div><div><b><span style="color: #6fa8dc;">The Economic Impact</span></b></div><div> One of the most striking aspects of this developer revolt is its economic implications. The collective action taken by these companies, which include well-known names like Voodoo.io, Azur Games, and SayGames, has essentially blocked Unity from generating any more revenue through their games. Each of these companies boasts a portfolio of over 100 games, making their decision to suspend monetization a significant financial blow to Unity. It's a powerful statement from developers who feel that their concerns are not being adequately addressed.</div><div><br /></div><div><br /></div><div><b><span style="color: #6fa8dc;">A Breach of Trust</span></b></div><div> Beyond the monetary concerns, the developers are fueled by a sense of betrayal. Unity had previously established a level of transparency in its terms of service that is now perceived to be broken. This abrupt shift in pricing without clear guidelines on how it will be implemented has left many developers feeling left in the dark and questioning their trust in Unity.</div><div><br /></div><div><br /></div><div><b><span style="color: #6fa8dc;">Unity's Dilemma</span></b></div><div> In the face of mounting pressure from developers, Unity finds itself at a crossroads. The company must navigate the delicate balance between revenue generation and maintaining a positive relationship with its user base. The collective action taken by these developers represents a pivotal moment in the ongoing struggle between Unity and its community. The outcome will undoubtedly shape the future of game development on the Unity platform.</div><div><br /></div><div><br /></div><div> Unity's new pricing model has ignited a fierce reaction from game developers, culminating in a collective suspension of monetization in their projects. This uprising not only highlights the financial impact on Unity but also underscores the importance of transparency and trust in the developer-platform relationship. The battle between Unity and its users is far from over, and its resolution will have far-reaching implications for the gaming industry as a whole.</div></div></div>Jordon McClainhttp://www.blogger.com/profile/18342097908172252205noreply@blogger.com0tag:blogger.com,1999:blog-3257117917071262914.post-87556593940795447702023-09-23T14:47:00.008-07:002023-09-26T05:00:06.706-07:0091.) Mastering First-Person Camera Controls: Preventing Y-Angle Flipping in Your Game<p style="text-align: center;"> <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtsXJxieGdF9l5uUiWdJGBbBiOY8qP8MoTJWo8cV4x6VtNaUjP-XxxY2MtlY5iK1AYdz9aFHV5HSBpIhtf6U__xILb0bVQCpOyIoQju_sg_YJxf4mFn2CUmUxc9gRyfDYTdef6oK896Yhut-2WTo3h3AxFnKO3LVA8vvWP5DbkpEfjGSymv5xX3DWRaVY/s1920/FPS-v2.png" style="clear: left; display: inline; margin-bottom: 1em; margin-right: 1em; text-align: left;"><img border="0" data-original-height="1080" data-original-width="1920" height="371" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtsXJxieGdF9l5uUiWdJGBbBiOY8qP8MoTJWo8cV4x6VtNaUjP-XxxY2MtlY5iK1AYdz9aFHV5HSBpIhtf6U__xILb0bVQCpOyIoQju_sg_YJxf4mFn2CUmUxc9gRyfDYTdef6oK896Yhut-2WTo3h3AxFnKO3LVA8vvWP5DbkpEfjGSymv5xX3DWRaVY/w658-h371/FPS-v2.png" width="658" /></a><br /><br /></p><p> In the world of game development, creating an immersive first-person experience is a key goal for many developers. One of the fundamental aspects of achieving this goal is getting your camera controls just right. However, a common issue that plagues many first-person games is the Y-angle flipping problem. Character movement and camera control are critical aspects of creating an immersive gaming experience. In this blog post, we'll discuss a common issue in character movement using XNA (Microsoft XNA Community Game Platform): preventing the character's head from flipping or rotating too far on the vertical (Y) axis. We'll provide you with a step-by-step guide on how to restrict the vertical rotation of your character's head to keep it within a specified range. Lets dive into this issue and show you how to prevent it in your game. We will test this first with the original XNA 4.0 Basic FPS Kit inspired by Starship Troopers for you to experiment and try yourself and then another example based on the XNA Chase Camera Sample.</p><p><br /></p><p><b><span style="color: #6fa8dc;">How to Prevent the Y-Angle from Flipping with the XNA 4.0 Basic FPS Kit</span></b> <br /><br /><iframe frameborder="0" height="180" src="https://www.indiedb.com/company/steel-cyclone-studios/downloads/xna-40-basic-fps/widget" width="600"></iframe><br /><br /></p><p><b><span style="color: #e06666;">The Y-Angle Flipping Problem</span></b></p><p> Before we dive into the solution, let's understand the problem. In many first-person games, the camera is controlled by the player's mouse movements. When a player looks up or down, the Y-angle of the camera changes. However, without proper handling, this can lead to a frustrating experience where the camera flips upside down when the player looks too far up or down.<br /></p><p> Imagine you have a character in your game, and you want players to control the character's viewpoint. However, you don't want the character's head to flip or rotate upside down, as it can break the immersion and create an unrealistic experience for players.</p><p><br /></p><p><b><span style="color: #93c47d;">The Solution: Clamping the Y-Angle</span></b></p><p> The solution to preventing Y-angle flipping is to clamp the Y-angle within a certain range. This ensures that the camera can't rotate too far up or down, keeping the player's perspective consistent and avoiding the dreaded flip.</p><p><br /></p><p>Here's a step-by-step guide to implementing this solution in the fps kit:</p><p><b>1. Track Mouse Movements</b></p><p>First, you'll want to track the player's mouse movements. Most game development libraries provide functions to get the mouse's current position.</p><p><br /></p><p>MouseState mouse = Mouse.GetState();</p><p>float deltaX = (mouse.X - centerX) * TurnSpeed * 0.01f;</p><p>float deltaY = (mouse.Y - centerY) * TurnSpeed * 0.01f;</p><p><br /></p><p><b>2. Update Y-Angle</b></p><p>Update the Y-angle (horizontal rotation) of your camera based on the horizontal mouse movement.</p><p>Angle.Y += MathHelper.ToRadians(deltaX);</p><p><br /></p><p><b>3. Clamp the X-Angle</b></p><p>Now comes the critical part. You'll want to clamp the X-angle (vertical rotation) to prevent it from going too far up or down. Use MathHelper.Clamp to restrict the angle within a reasonable range.</p><p>Angle.X = MathHelper.Clamp(Angle.X + MathHelper.ToRadians(deltaY), -MathHelper.PiOver2, MathHelper.PiOver2);</p><p>With this clamping in place, your camera will never flip upside down, no matter how far the player looks up or down.</p><p><br /></p><p><b>4. Implement Camera Movement</b></p><p> Of course, camera controls involve more than just looking around. You'll also want to implement movement controls, such as forward, backward, strafing left, and strafing right. The specifics of this will depend on your game engine and architecture, but ensure that these movements take the camera's orientation into account.</p><p><br /></p><p><b>5. Apply the Camera Transformation</b></p><p>Finally, don't forget to update the camera's view matrix or equivalent transformation based on the camera's position and orientation. This matrix is crucial for rendering the game world correctly from the player's perspective. The source code with the solution provided above is available to download below.</p><p><br /></p><iframe frameborder="0" height="180" src="https://www.indiedb.com/company/steel-cyclone-studios/downloads/xna-40-basic-fps-v2/widget" width="600"></iframe><br /><br /><p><br /></p><p> <br /><b><span style="color: #6fa8dc;">First-Person Camera Flip Prevention Example 2</span></b><br /> We'll show you how to solve this problem using another example based off the Chase Camera Sample.</p><p><b>Step 1: Define a Maximum Rotation Limit</b></p><p>To prevent the character's head from flipping too far, you need to define a maximum rotation limit. This limit determines the maximum angle (in radians) your character's head can rotate on the vertical (Y) axis. You can adjust this limit based on your game's requirements. Here's how to define it:</p><p>float maxYRotation = MathHelper.ToRadians(80); // Set the maximum allowed Y rotation in radians (adjust as needed)</p><p>In this example, we've set maxYRotation to 80 degrees. Feel free to change this value to match your desired rotation limit.</p><p><br /></p><p><b>Step 2: Clamp the Rotation Amount</b></p><p>Next, you need to ensure that the rotation amount (rotationAmount.Y) stays within the specified range. To do this, use the MathHelper.Clamp function:</p><p>rotationAmount.Y = MathHelper.Clamp(rotationAmount.Y, -maxYRotation, maxYRotation);</p><p>This line of code restricts the vertical rotation (rotationAmount.Y) to stay within the range of -maxYRotation (negative limit) and maxYRotation (positive limit).</p><p><br /></p><p><b>Step 3: Create the Rotation Matrix</b></p><p>With the rotation amount clamped to the specified range, you can create a rotation matrix that represents the character's head orientation. This matrix ensures that the character's head remains within the allowed rotation limits:</p><p>rotationMatrix =</p><p> Matrix.CreateFromAxisAngle(Right, rotationAmount.Y) *</p><p> Matrix.CreateRotationY(rotationAmount.X);</p><p><br /></p><p> This code creates the rotation matrix using both the vertical (Y-axis) and horizontal (X-axis) rotation amounts. The Right vector is used to determine the axis of rotation. By following these three simple steps, you can prevent your character's head from flipping or rotating too far on the vertical axis in XNA. This not only enhances the realism of your game but also ensures a smoother and more immersive gaming experience for your players. Remember to adjust the maxYRotation value to suit your game's specific needs. With this control in place, you can create more enjoyable and realistic character movement and camera control in your XNA games.</p><p><b><br />Conclusion</b></p><p> In the world of game development, smooth and intuitive first-person camera controls are essential for creating an immersive experience. By understanding and addressing the Y-angle flipping problem, you can provide players with a more enjoyable and frustration-free gaming experience.</p><p> Implementing these solutions will go a long way in improving your game's camera controls, making it more enjoyable and engaging for players. So, go ahead and give it a try in your next game project, and watch as your players appreciate the smoother, more immersive experience you've created. Happy coding!</p>Jordon McClainhttp://www.blogger.com/profile/18342097908172252205noreply@blogger.com0tag:blogger.com,1999:blog-3257117917071262914.post-7778396830625493762023-09-08T04:42:00.000-07:002023-09-08T04:42:27.903-07:0090.) Creating the Credits Screen for our Menu System<p> Hello fellow game developers! In this blog post, we'll dive into the inner workings of the credits screen for our menu system. The credits screen is an essential component of many games, as it provides recognition to the talented individuals who contributed to the game's development. Let's take a closer look at the code and functionality of this CreditsScreen class.<br /><br /><b><span style="color: #3d85c6;">Code in Full: </span></b><br /></p><p>#region Using Statements</p><p>using System;<br />using System.IO;<br />using System.Collections.Generic;<br />using System.Linq;<br />using System.Text;<br />using Microsoft.Xna.Framework;<br />using Microsoft.Xna.Framework.Content;<br />using Microsoft.Xna.Framework.Graphics;<br />using Microsoft.Xna.Framework.Storage;</p><p>#endregion</p><p><br /></p><p>namespace GameStateManagement<br />{</p><p> /// <summary></p><p> /// The credits screen is brought up over the top of the main menu</p><p> /// screen, and provides the viewers a professional credit roll of all</p><p> /// who worked on the game.</p><p> /// </summary></p><p> class CreditsScreen : MenuScreen<br /> {</p><p> #region Fields</p><p> private Texture2D m_t2d_BackgroundTexture;</p><p> private Vector2 m_v2_BackgroundPosition, m_v2_BackgroundOrigin;</p><p> ContentManager content;</p><p> private float m_f_Scroll;</p><p><br /></p><p> private int[] m_i_FontHeight = null;</p><p> /// <summary></p><p> /// List of names to draw</p><p> /// </summary></p><p> private string[] m_s_Names = null;</p><p><br /></p><p> // Create our menu entries.</p><p> MenuEntry backMenuEntry = new MenuEntry("Back");</p><p> String[] m_str_CreditEntries;</p><p> public bool m_b_HasInputBeenTouched = false;</p><p> #endregion</p><p><br /></p><p> #region Initialization</p><p> /// <summary></p><p> /// Constructor.</p><p> /// </summary></p><p> public CreditsScreen()</p><p> : base("Credits Menu")</p><p> {</p><p> MenuEntries.Add(backMenuEntry);</p><p> backMenuEntry.Selected += OnCancel;</p><p> }</p><p> #endregion</p><p><br /></p><p> #region Handle Input</p><p> public override void LoadContent()<br /> {</p><p> base.LoadContent();</p><p> if (content == null)</p><p> content = new ContentManager(ScreenManager.Game.Services, "Content");</p><p><br /></p><p> m_f_Scroll = ScreenManager.GraphicsDevice.Viewport.Height;</p><p> m_t2d_BackgroundTexture = content.Load<Texture2D>("background");</p><p><br /></p><p> m_v2_BackgroundOrigin = new Vector2(m_t2d_BackgroundTexture.Width / 2, m_t2d_BackgroundTexture.Height / 2);</p><p> m_v2_BackgroundPosition = new Vector2(m_t2d_BackgroundTexture.Width / 2, m_t2d_BackgroundTexture.Height / 2);</p><p><br /></p><p> m_str_CreditEntries = new String[126];</p><p> //load names from file - names are stored line by line</p><p> this.m_s_Names = File.ReadAllLines("Content/Names.txt");</p><p><br /></p><p> //create y coord for each name</p><p> this.m_i_FontHeight = new int[m_s_Names.Length];</p><p> int y = 0;//this.ScreenManager.GraphicsDevice.Viewport.Height / 2;</p><p><br /></p><p> for (int i = 0; i < this.m_i_FontHeight.Length; i++, y += this.ScreenManager.Font.LineSpacing)</p><p> this.m_i_FontHeight[i] = y;</p><p> SetMenuEntryText();</p><p> }</p><p><br /></p><p> private void SetMenuEntryText()</p><p> {</p><p> }</p><p><br /></p><p> new private void OnCancel(object sender, PlayerIndexEventArgs e)</p><p> {</p><p> base.OnCancel(sender, e);</p><p> }</p><p><br /></p><p> public override void Update(GameTime gameTime, bool otherScreenHasFocus,</p><p> bool coveredByOtherScreen)</p><p> { </p><p> // Make the menu slide into place during transitions, using a</p><p> // power curve to make things look more interesting (this makes</p><p> // the movement slow down as it nears the end).</p><p> float transitionOffset = (float)Math.Pow(TransitionPosition, 2);</p><p><br /></p><p> m_f_SpriteScale = ((transitionOffset - 1) * -1);</p><p> m_f_SpriteScale *= 1000.0f;</p><p><br /></p><p> if (!m_b_HasInputBeenTouched)</p><p> m_f_Scroll -= 175.0f * (float)gameTime.ElapsedGameTime.TotalSeconds;</p><p><br /></p><p> if (m_f_Scroll < -20096.25)</p><p> base.OnCancel(PlayerIndex.One);</p><p> base.Update(gameTime, otherScreenHasFocus, false);</p><p> }</p><p><br /></p><p> public override void HandleInput(InputState input)</p><p> {</p><p> base.HandleInput(input);</p><p><br /></p><p> //if (input.RightStickCurrent.Y > 0)</p><p> //{</p><p> m_b_HasInputBeenTouched = true;</p><p> m_f_Scroll -= 1.0f;</p><p> //}</p><p><br /></p><p> /* if (input.RightStickCurrent.Y < 0)</p><p> {</p><p> m_b_HasInputBeenTouched = true;</p><p> m_f_Scroll -= 10.0f;</p><p> }*/</p><p> }</p><p><br /></p><p> private float m_f_SpriteScale = 0.0f;</p><p> private Color m_col_FontColor;</p><p> public override void Draw(GameTime gameTime)</p><p> {</p><p> ScreenManager.SpriteBatch.Begin();</p><p> ScreenManager.SpriteBatch.Draw(m_t2d_BackgroundTexture, new Rectangle(0, 0, (ScreenManager.GraphicsDevice.Viewport.Width * (int)m_f_SpriteScale) / 1000, (ScreenManager.GraphicsDevice.Viewport.Height * (int)m_f_SpriteScale) / 1000), Color.White);</p><p> ScreenManager.SpriteBatch.End();</p><p> float transitionOffset = (float)Math.Pow(TransitionPosition, 2);</p><p> //draw names</p><p> this.ScreenManager.SpriteBatch.Begin();</p><p> for (int i = 0; i < this.m_s_Names.Length; i++)</p><p> {</p><p> Vector2 pos = new Vector2((this.ScreenManager.GraphicsDevice.Viewport.Width / 2 -</p><p> (this.ScreenManager.Font.MeasureString(this.m_s_Names[i]).X / 2)), this.m_i_FontHeight[i] + m_f_Scroll);</p><p> m_col_FontColor = Color.White;</p><p> if (pos.Y < 100 || pos.Y > ScreenManager.GraphicsDevice.Viewport.Height - 100)</p><p> m_col_FontColor.A = 0;</p><p> if (ScreenState == ScreenState.TransitionOn)</p><p> pos.X -= transitionOffset * 256;</p><p> else</p><p> pos.X += transitionOffset * 512;</p><p> this.ScreenManager.SpriteBatch.DrawString(this.ScreenManager.Font, this.m_s_Names[i], pos, m_col_FontColor);</p><p> }</p><p> this.ScreenManager.SpriteBatch.End();</p><p> base.Draw(gameTime);</p><p> }</p><p> #endregion</p><p> }</p><p>}</p><div><br /></div><p><b><span style="color: #3d85c6;">Introduction</span><br /> </b>The CreditsScreen class is part of a game project that utilizes the Microsoft XNA framework for game development. It serves as an overlay on top of the main menu screen and presents a professional-looking credit roll of all the people who worked on the game.<br /><br /><br /><b><span style="color: #3d85c6;">Fields and Initialization</span><br /></b></p><p>#region Using Statements</p><p>// Import necessary namespaces</p><p>using System;</p><p>using System.IO;</p><p>using System.Collections.Generic;</p><p>using System.Linq;</p><p>using System.Text;</p><p>using Microsoft.Xna.Framework;</p><p>using Microsoft.Xna.Framework.Content;</p><p>using Microsoft.Xna.Framework.Graphics;</p><p>using Microsoft.Xna.Framework.Storage;</p><p></p><p>#endregion</p><div>The <b><span style="color: #6aa84f;">'using'</span></b> statements at the beginning of the class import the required namespaces for XNA game development.</div><div><br /></div><div><br /></div><div><div>class CreditsScreen : MenuScreen</div><div>{</div><div> // Fields for textures, positions, and content</div><div> private Texture2D m_t2d_BackgroundTexture;</div><div> private Vector2 m_v2_BackgroundPosition, m_v2_BackgroundOrigin;</div><div> ContentManager content;</div><div> private float m_f_Scroll;</div><div><br /></div><div> // Arrays to store font heights and credit entries</div><div> private int[] m_i_FontHeight = null;</div><div> private string[] m_s_Names = null;</div><div><br /></div><div> // Menu entry for returning to the main menu</div><div> MenuEntry backMenuEntry = new MenuEntry("Back");</div><div><br /></div><div> String[] m_str_CreditEntries;</div><div><br /></div><div> public bool m_b_HasInputBeenTouched = false;</div></div><div><br /></div><div><br /> Here, we declare various fields for managing textures, positions, and content, as well as arrays to store font heights and credit entries. We also create a menu entry labeled "Back" to allow the player to return to the main menu.</div><div><br /></div><div><br /></div><div><b><span style="color: #3d85c6;">Initialization</span></b></div><div><b><br /></b></div><div><div>public CreditsScreen()</div><div> : base("Credits Menu")</div><div>{</div><div> MenuEntries.Add(backMenuEntry);</div><div> backMenuEntry.Selected += OnCancel;</div><div>}</div></div><div><br /></div><div> The constructor initializes the CreditsScreen class by setting its name and adding the "Back" menu entry. Additionally, it hooks up an event handler for when the "Back" menu entry is selected.</div><div><br /></div><div><br /></div><div><b><span style="color: #3d85c6;">LoadContent</span><br /><br /></b></div><div><div>public override void LoadContent()</div><div>{</div><div> base.LoadContent();</div><div><br /></div><div> if (content == null)</div><div> content = new ContentManager(ScreenManager.Game.Services, "Content");</div><div><br /></div><div> m_f_Scroll = ScreenManager.GraphicsDevice.Viewport.Height;</div><div><br /></div><div> // Load background texture</div><div> m_t2d_BackgroundTexture = content.Load<Texture2D>("background");</div><div><br /></div><div> m_v2_BackgroundOrigin = new Vector2(m_t2d_BackgroundTexture.Width / 2, m_t2d_BackgroundTexture.Height / 2);</div><div> m_v2_BackgroundPosition = new Vector2(m_t2d_BackgroundTexture.Width / 2, m_t2d_BackgroundTexture.Height / 2);</div><div><br /></div><div> m_str_CreditEntries = new String[126];</div><div><br /></div><div> // Load names from a file</div><div> this.m_s_Names = File.ReadAllLines("Content/Names.txt");</div><div><br /></div><div> // Create Y coordinates for each name</div><div> this.m_i_FontHeight = new int[m_s_Names.Length];</div><div><br /></div><div> int y = 0;</div><div><br /></div><div> for (int i = 0; i < this.m_i_FontHeight.Length; i++, y += this.ScreenManager.Font.LineSpacing)</div><div> this.m_i_FontHeight[i] = y;</div><div><br /></div><div> SetMenuEntryText();</div><div>}</div><div><br /> In the <b><span style="color: #6aa84f;">'LoadContent'</span></b> method, we load the required content, such as the background texture and the list of names, from external files. We also set up Y coordinates for each name to control their position on the screen.</div><div><br /></div><div><br /></div><div><b><span style="color: #3d85c6;">Handle Input </span><br /></b><br /><div>public override void HandleInput(InputState input)</div><div>{</div><div> base.HandleInput(input);</div><div><br /></div><div> m_b_HasInputBeenTouched = true;</div><div> m_f_Scroll -= 1.0f;</div><div>}</div><div><br /> The <b><span style="color: #6aa84f;">'HandleInput'</span></b> method allows the player to interact with the credits screen. In this implementation, we scroll the credits by decreasing the <b><span style="color: #6aa84f;">'m_f_Scroll'</span></b> value when input is detected. You can customize this behavior according to your game's needs, such as allowing the player to scroll with different input methods.<br /><br /><br /><b><span style="color: #3d85c6;">Update & Draw</span></b><br /><div> The Update and Draw methods handle the animation and rendering of the credits roll. The key points are as follows:</div><div><ul style="text-align: left;"><li>The <b><span style="color: #6aa84f;">'Update'</span></b> method uses a power curve to make the movement look interesting, gradually slowing down as it nears the end of the credits.<br /><br /></li><li>The <b><span style="color: #6aa84f;">'Draw'</span></b> method renders the background and credit text. It adjusts the position and transparency of the text based on the current transition state.</li></ul><div><br /></div><div><div> In conclusion, creating a credits screen for your game is an essential way to give credit to your development team and contributors. This CreditsScreen class provides a foundation for creating a professional-looking credits roll in your game. You can customize it further to fit the style and requirements of your game's menu system. Feel free to adapt and extend this code to create a unique credits screen for your game project. Happy coding!</div></div><div><br /></div><div><br /></div></div></div></div></div>Jordon McClainhttp://www.blogger.com/profile/18342097908172252205noreply@blogger.com0tag:blogger.com,1999:blog-3257117917071262914.post-91427294592765666792023-08-05T06:28:00.014-07:002023-08-29T05:37:51.419-07:0089.) Code Performance Optimization<div style="text-align: center;"><iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen="" frameborder="0" height="351" src="https://www.youtube.com/embed/3W09FapjBhg" title="YouTube video player" width="624"></iframe></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: left;"><div> In the realm of game and application development, achieving optimal performance is a perpetual pursuit. It's a delicate balance between harnessing the capabilities of hardware and software while ensuring a seamless user experience. One crucial aspect of this endeavor involves fine-tuning graphics settings and physics configurations. In this blog, we'll delve into a code snippet that highlights common practices and improvements that can be made to enhance both graphics rendering and physics simulations.</div><div><br /></div><div> The provided code snippet outlines a series of settings related to graphics and a physics system. While functional, it leaves room for refinement. We'll break down the code, step by step, and explore how each segment can be optimized to deliver a smoother, more visually appealing, and responsive experience. From selecting the optimal display resolution to streamlining redundant settings and fine-tuning physics parameters, we'll guide you through a process that aims to elevate your application's performance.</div><div><br /></div><div> Join me as I embark on a journey to transform the given code into a well-optimized and efficient piece of software. By the end of this blog, you'll have a clearer understanding of how to make the most out of your graphics and physics settings, ensuring that your XNA and MonoGame applications shine in terms of both performance and user satisfaction. Let's dive in and uncover the secrets to achieving a finely-tuned, high-performance application.</div></div><div style="text-align: center;"><br /></div><div style="text-align: left;"><b><span style="color: #6fa8dc;">How I Optimized the Graphics Display Settings</span></b><br /><br /><div>how can the following be improved: <br /><br /></div><div> graphics.SynchronizeWithVerticalRetrace = true;</div><div> this.IsFixedTimeStep = false;</div><div> graphics.IsFullScreen = true;</div><div><br /></div><div> physicSystem = new PhysicsSystem();</div><div> graphics.PreferMultiSampling = true;</div><div><br /></div><div> //graphics.PreferredBackBufferWidth = 2560;</div><div> //graphics.PreferredBackBufferHeight = 1600;</div><div> graphics.PreferredBackBufferWidth = 3840;</div><div> graphics.PreferredBackBufferHeight = 2160;</div><div><br /></div><div> graphics.SynchronizeWithVerticalRetrace = false;</div><div> graphics.ApplyChanges();</div><div> this.IsFixedTimeStep = false;</div><div> //physicSystem.CollisionSystem = new CollisionSystemGrid(32, 32, 32, 30, 30, 30);</div><div> //physicSystem.CollisionSystem = new CollisionSystemBrute();</div><div> physicSystem.CollisionSystem = new CollisionSystemSAP();</div><div><br /></div><div> physicSystem.EnableFreezing = true;</div><div> physicSystem.SolverType = PhysicsSystem.Solver.Normal;</div><div> physicSystem.CollisionSystem.UseSweepTests = true;</div><div><br /></div><div> physicSystem.NumCollisionIterations = 10;</div><div> physicSystem.NumContactIterations = 10;</div><div> physicSystem.NumPenetrationRelaxtionTimesteps = 15;</div><div><br /></div><div>To improve the provided code, we can focus on optimizing graphics settings and physics system configurations. Here are some suggestions:</div><div><br /></div><div>Use PreferredBackBufferWidth and PreferredBackBufferHeight based on the monitor resolution: Instead of setting an arbitrary resolution, consider checking the available display resolutions and select the most appropriate one based on the user's monitor.</div><div><br /></div><div>Avoid redundant settings: There are some settings applied multiple times, such as IsFixedTimeStep and SynchronizeWithVerticalRetrace. You can remove redundant lines of code to keep the configuration clean.</div><div><br /></div><div>Optimize physics settings: The physics system configuration can significantly impact performance. You can fine-tune the physics parameters based on your specific requirements.</div><div><br /></div><div>Here's the improved version of the code:<br /><br /></div><div>graphics.IsFullScreen = true;</div><div>graphics.PreferMultiSampling = true;</div><div><br /></div><div>// Check available display resolutions and choose the most appropriate one</div><div>DisplayModeCollection displayModes = GraphicsAdapter.DefaultAdapter.SupportedDisplayModes;</div><div>DisplayMode preferredDisplayMode = FindBestDisplayMode(displayModes);</div><div>graphics.PreferredBackBufferWidth = preferredDisplayMode.Width;</div><div>graphics.PreferredBackBufferHeight = preferredDisplayMode.Height;</div><div><br /></div><div>graphics.ApplyChanges();</div><div><br /></div><div>physicSystem = new PhysicsSystem();</div><div>physicSystem.CollisionSystem = new CollisionSystemSAP();</div><div><br /></div><div>physicSystem.EnableFreezing = true;</div><div>physicSystem.SolverType = PhysicsSystem.Solver.Normal;</div><div>physicSystem.CollisionSystem.UseSweepTests = true;</div><div><br /></div><div>physicSystem.NumCollisionIterations = 10;</div><div>physicSystem.NumContactIterations = 10;</div><div>physicSystem.NumPenetrationRelaxtionTimesteps = 15;</div><div><br /></div><div> In this improved version, we select the preferred display mode based on the available display resolutions, clean up redundant settings, and focus on fine-tuning the physics system parameters.</div><div><br /></div><div><b>Note:</b> The FindBestDisplayMode function is not shown in the code above since it depends on the specific implementation and available display modes. You can implement it to choose the best display mode based on your requirements and available options.</div><div><br /></div><div><br /></div><div><b><span style="color: #6aa84f;">Implement FindBestDisplayMode</span></b></div><div> Implementing the FindBestDisplayMode function involves selecting the most appropriate display mode from the available display modes based on specific criteria. Here's one way you can do it:</div><div>using Microsoft.Xna.Framework.Graphics;</div><div><br /></div><div><span style="color: #93c47d;">// Function to find the best display mode based on specific criteria</span></div><div>private DisplayMode FindBestDisplayMode(DisplayModeCollection displayModes)</div><div>{</div><div> <span style="color: #93c47d;">// Set the initial values for the best display mode</span></div><div> DisplayMode bestDisplayMode = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode;</div><div> SurfaceFormat bestFormat = bestDisplayMode.Format;</div><div> int bestWidth = bestDisplayMode.Width;</div><div> int bestHeight = bestDisplayMode.Height;</div><div><br /></div><div><span style="color: #93c47d;"> // Iterate through all available display modes and select the best one</span></div><div> foreach (DisplayMode displayMode in displayModes)</div><div> {</div><div><span style="color: #93c47d;"> // You can add specific criteria here to filter display modes</span></div><div><span style="color: #93c47d;"> // For example, you may want to select modes with a specific aspect ratio or minimum resolution.</span></div><div><span style="color: #93c47d;"><br /></span></div><div><span style="color: #93c47d;"> // In this example, we prioritize higher resolutions and color depth.</span></div><div> if (displayMode.Width > bestWidth || displayMode.Height > bestHeight</div><div> || (displayMode.Width == bestWidth && displayMode.Height == bestHeight && displayMode.Format > bestFormat))</div><div> {</div><div> bestDisplayMode = displayMode;</div><div> bestFormat = displayMode.Format;</div><div> bestWidth = displayMode.Width;</div><div> bestHeight = displayMode.Height;</div><div> }</div><div> }</div><div><br /></div><div> return bestDisplayMode;</div><div>}</div><div><br /></div><div> In this implementation, we start with the current display mode as the initial best display mode. Then, we iterate through all the available display modes and compare them based on the specific criteria. In this version, we use the Format property to compare the color depth of display modes. We still prioritize higher resolutions and color depth to determine the best display mode for your application. You can adjust the criteria in the comparison to suit your specific needs. </div><div><br /></div><div> Please note that different platforms and graphics adapters may have different available display modes, so the best display mode will depend on the system's capabilities. This function gives you a starting point to choose the best display mode for your application based on your desired criteria.</div><div><br /></div><div><br /></div><div><b><span style="color: #6fa8dc;">How I improved the JigLibX Physics Simulation Time Step</span></b></div><div><div><br />The code before was the following: <br /><br /></div><div> float timeStep = (float)gameTime.ElapsedGameTime.Ticks / TimeSpan.TicksPerSecond;</div><div> if (timeStep < 1.0f / 120.0f) physicSystem.Integrate(timeStep);</div><div> else physicSystem.Integrate(1.0f / 120.0f);</div><div><br /></div><div> The provided code is used to control the physics simulation time step and ensure that it doesn't become too large, which could negatively impact the accuracy and stability of the physics simulation. However, we can improve the code by considering the following:</div><div><br /></div><div> Use TimeSpan.TotalSeconds for a more straightforward and accurate representation of the elapsed time. Limit the maximum time step to avoid large fluctuations in the physics simulation.</div><div><br /></div><div>Here's an improved version of the code:</div><div><br /></div><div> double maxTimeStep = 1.0 / 120.0; <span style="color: #93c47d;">// Maximum time step allowed (1/120 seconds)</span></div><div> double elapsedSeconds = gameTime.ElapsedGameTime.TotalSeconds;</div><div> double timeStep = Math.Min(elapsedSeconds, maxTimeStep);</div><div> physicSystem.Integrate((float)timeStep);<br /><br /><br /><div>There's a small optimization that can be applied to avoid the need to convert the time step from double to float when calling the Integrate method.</div><div><br /></div>Here's the improved version of the code:: <br /><br /><div> double maxTimeStep = 1.0 / 120.0; // Maximum time step allowed (1/120 seconds)</div><div> double elapsedSeconds = gameTime.ElapsedGameTime.TotalSeconds;</div><div> float timeStep = (float)Math.Min(elapsedSeconds, maxTimeStep);</div><div> physicSystem.Integrate(timeStep);</div></div><div><br /></div><div> In this improved version, we directly use TimeSpan.TotalSeconds to get the elapsed time in seconds. We then limit the timeStep to be at most maxTimeStep to ensure it doesn't become too large. By doing so, we strike a balance between maintaining accuracy and preventing large time steps, leading to a more stable physics simulation.</div></div><div><br /></div><div><br /></div><div><b><span style="color: #6fa8dc;">How to Improve the Draw Method</span></b></div><div><br /></div><div><div>Old draw method:<br /><br /></div><div>Matrix[] transforms = new Matrix[house2.Bones.Count];</div><div> house2.CopyAbsoluteBoneTransformsTo(transforms);</div><div><br /></div><div><br /></div><div> <span style="color: #93c47d;">//foreach (ModelMesh houseMesh in house2.Meshes)</span></div><div> for (int i = 0; i < house2.Meshes.Count; i++)</div><div> {</div><div> ModelMesh houseMesh = house2.Meshes[i];</div><div> for (int j = 0; j < houseMesh.Effects.Count; j++)</div><div> //foreach (BasicEffect be in houseMesh.Effects)</div><div> {</div><div> BasicEffect be = (BasicEffect)houseMesh.Effects[j];</div><div> be.World =</div><div> transforms[houseMesh.ParentBone.Index] *</div><div> Matrix.Identity;</div><div><br /></div><div><br /></div><div> be.EnableDefaultLighting();</div><div><span style="color: #93c47d;"> // be.DiffuseColor = new Vector3(5.8f); // city texture lighting</span></div><div><span style="color: #93c47d;"> //be.SpecularColor = new Vector3(0.3f);</span></div><div> be.SpecularPower = 5;</div><div><br /></div><div> be.View = camera.View;</div><div> be.Projection = camera.Projection;</div><div> }</div><div> houseMesh.Draw();</div><div> }</div><div><br /></div><div><br /></div><div>To improve the performance of the code, you can take the following steps:</div><div><br /></div><div>1.) Move the creation and copying of transforms array outside the loop: Since the transforms array doesn't depend on the loop, you can calculate it once outside the loop to avoid unnecessary overhead.</div><div><br /></div><div>2.) Cache the count values: Instead of calling house2.Bones.Count and houseMesh.Effects.Count in each iteration, store their counts in variables before the loops.</div><div><br /></div><div>3.) Use the foreach loop for iterating through meshes if possible: The foreach loop can sometimes offer better performance because it handles the internal iteration logic more efficiently than a for loop. </div><div><br /></div><div>Here's the optimized code:</div><div><br /></div><div>Matrix[] transforms = new Matrix[house2.Bones.Count];</div><div>house2.CopyAbsoluteBoneTransformsTo(transforms);</div><div><br /></div><div>int numMeshes = house2.Meshes.Count;</div><div><br /></div><div>foreach (ModelMesh houseMesh in house2.Meshes)</div><div>{</div><div> int numEffects = houseMesh.Effects.Count;</div><div><br /></div><div> for (int j = 0; j < numEffects; j++)</div><div> {</div><div> BasicEffect be = (BasicEffect)houseMesh.Effects[j];</div><div><br /></div><div> be.World = transforms[houseMesh.ParentBone.Index] * Matrix.Identity;</div><div> be.EnableDefaultLighting();</div><div> be.SpecularPower = 5;</div><div> be.View = camera.View;</div><div> be.Projection = camera.Projection;</div><div> }</div><div> houseMesh.Draw();</div><div>}</div><div><br /></div><div> By following these steps, you reduce unnecessary calculations and calls, which should lead to improved performance. Remember that performance optimization can be a complex topic and may depend on other parts of your code and hardware, so it's essential to profile and test to see the actual improvements.</div></div><div><br /></div><div><br /></div><div><b><span style="color: #6fa8dc;">How I Optimized the Skybox</span></b></div><div><br /></div><div><div>Old Skybox Source Code: </div><div><br /></div><div>using Microsoft.Xna.Framework.Graphics;</div><div>using Microsoft.Xna.Framework.Content;</div><div>using Microsoft.Xna.Framework;</div><div><br /></div><div>namespace JiggleGame</div><div>{</div><div> public class SkyBox</div><div> {</div><div> JiggleGame Game;</div><div> Model skyBoxModel;</div><div> Texture2D[] skyBoxTextures;</div><div><br /></div><div> Vector3 center;</div><div> float rotation = 0;</div><div><br /></div><div> public SkyBox(JiggleGame newGame, Vector3 newCenter, string newName)</div><div> {</div><div> Game = newGame;</div><div> center = newCenter;</div><div><br /></div><div> skyBoxModel = LoadModel(newName, out skyBoxTextures);</div><div> }</div><div><br /></div><div><br /></div><div> private Model LoadModel(string assetName, out Texture2D[] textures)</div><div> {</div><div> Model newModel = Game.Content.Load<Model>(assetName);</div><div> textures = new Texture2D[newModel.Meshes.Count];</div><div> int i = 0;</div><div><br /></div><div> foreach (ModelMesh mesh in newModel.Meshes)</div><div> {</div><div> foreach (BasicEffect currentEffect in mesh.Effects)</div><div> {</div><div> textures[i++] = currentEffect.Texture;</div><div> }</div><div> }</div><div> foreach (ModelMesh mesh in newModel.Meshes)</div><div> {</div><div> foreach (ModelMeshPart meshPart in mesh.MeshParts)</div><div> {</div><div> meshPart.Effect = Game.skyEffect.Clone();</div><div> }</div><div> }</div><div><br /></div><div> return newModel;</div><div> }</div><div> public void Draw(Vector3 center)</div><div> {</div><div> SamplerState ss = new SamplerState();</div><div> ss.AddressU = TextureAddressMode.Clamp;</div><div> ss.AddressV = TextureAddressMode.Clamp;</div><div> Game.GraphicsDevice.SamplerStates[0] = ss;</div><div><br /></div><div> DepthStencilState dss = new DepthStencilState();</div><div> dss.DepthBufferEnable = false;</div><div> <span style="color: #93c47d;"> // Game.GraphicsDevice.DepthStencilState = dss;</span></div><div><br /></div><div> Matrix[] skyboxTransforms = new Matrix[skyBoxModel.Bones.Count];</div><div> skyBoxModel.CopyAbsoluteBoneTransformsTo(skyboxTransforms);</div><div> int i = 0;</div><div> foreach (ModelMesh mesh in skyBoxModel.Meshes)</div><div> {</div><div> foreach (Effect currentEffect in mesh.Effects)</div><div> {</div><div> Matrix worldMatrix =<span style="color: #93c47d;"> /*Matrix.CreateRotationY(rotation+=0.0001f) **/</span> Matrix.CreateScale(5000f) * skyboxTransforms[mesh.ParentBone.Index] * Matrix.CreateTranslation(center);</div><div> currentEffect.CurrentTechnique = currentEffect.Techniques["Sky"];</div><div> currentEffect.Parameters["xWorld"].SetValue(skyboxTransforms[mesh.ParentBone.Index] * worldMatrix);</div><div> currentEffect.Parameters["xViewProjection"].SetValue(Game.camera.View * Game.camera.Projection);</div><div> currentEffect.Parameters["xTexture"].SetValue(skyBoxTextures[i++]);</div><div><br /></div><div> <span style="color: #93c47d;"> // Game.texturedEffect.Parameters["xGrayScale"].SetValue(Game.enviro.grayScale);</span></div><div><br /></div><div> }</div><div> mesh.Draw();</div><div> }</div><div><br /></div><div> }</div><div> }</div><div>}</div><div><br /></div><div><br /></div><div><br /></div><div>1.) To improve the performance of the SkyBox class, we can make several changes. The main areas of improvement include reducing redundant computations, minimizing object creation, and avoiding unnecessary iterations.</div><div><br /></div><div>2.) Move the creation of SamplerState and DepthStencilState outside the Draw method. They don't need to be created on each frame but can be done once during initialization.</div><div><br /></div><div>3.) Avoid using string-based parameter lookups like "Sky" for techniques. Instead, use constants or predefined variables to reference the specific technique.</div><div><br /></div><div>4.) Cache the View and Projection matrices of the camera outside the Draw method. Since they are unlikely to change frequently, there's no need to calculate them every frame.</div><div><br /></div><div>5.) Instead of iterating over all the meshes and their effects separately, we can combine these loops to reduce iterations.</div><div><br /></div><div>Here's the modified code with these improvements:</div><div><br /></div><div>using Microsoft.Xna.Framework.Graphics;</div><div>using Microsoft.Xna.Framework.Content;</div><div>using Microsoft.Xna.Framework;</div><div><br /></div><div>namespace JiggleGame</div><div>{</div><div> public class SkyBox</div><div> {</div><div> private JiggleGame Game;</div><div> private Model skyBoxModel;</div><div> private Texture2D[] skyBoxTextures;</div><div> private Effect skyEffect;</div><div> private Matrix[] skyboxTransforms;</div><div> private SamplerState samplerState;</div><div> private DepthStencilState depthStencilState;</div><div> private const string SkyTechniqueName = "Sky";</div><div><br /></div><div> public SkyBox(JiggleGame newGame, Vector3 newCenter, string newName)</div><div> {</div><div> Game = newGame;</div><div> skyEffect = Game.skyEffect;</div><div><br /></div><div> skyBoxModel = LoadModel(newName, out skyBoxTextures);</div><div><br /></div><div> samplerState = new SamplerState</div><div> {</div><div> AddressU = TextureAddressMode.Clamp,</div><div> AddressV = TextureAddressMode.Clamp</div><div> };</div><div><br /></div><div> depthStencilState = new DepthStencilState</div><div> {</div><div> DepthBufferEnable = false</div><div> };</div><div><br /></div><div> skyboxTransforms = new Matrix[skyBoxModel.Bones.Count];</div><div> skyBoxModel.CopyAbsoluteBoneTransformsTo(skyboxTransforms);</div><div> }</div><div><br /></div><div> private Model LoadModel(string assetName, out Texture2D[] textures)</div><div> {</div><div> Model newModel = Game.Content.Load<Model>(assetName);</div><div> textures = new Texture2D[newModel.Meshes.Count];</div><div><br /></div><div> for (int i = 0; i < newModel.Meshes.Count; i++)</div><div> {</div><div> ModelMesh mesh = newModel.Meshes[i];</div><div> textures[i] = ((BasicEffect)mesh.Effects[0]).Texture;</div><div> foreach (ModelMeshPart meshPart in mesh.MeshParts)</div><div> {</div><div> meshPart.Effect = skyEffect.Clone();</div><div> }</div><div> }</div><div><br /></div><div> return newModel;</div><div> }</div><div><br /></div><div> public void Draw(Vector3 center)</div><div> {</div><div> Game.GraphicsDevice.SamplerStates[0] = samplerState;</div><div> //Game.GraphicsDevice.DepthStencilState = depthStencilState;</div><div><br /></div><div> for (int i = 0; i < skyBoxModel.Meshes.Count; i++)</div><div> {</div><div> ModelMesh mesh = skyBoxModel.Meshes[i];</div><div> Effect currentEffect = mesh.Effects[0];</div><div> Matrix worldMatrix = Matrix.CreateScale(5000f) * skyboxTransforms[mesh.ParentBone.Index] * Matrix.CreateTranslation(center);</div><div> currentEffect.CurrentTechnique = currentEffect.Techniques[SkyTechniqueName];</div><div> currentEffect.Parameters["xWorld"].SetValue(worldMatrix);</div><div> currentEffect.Parameters["xViewProjection"].SetValue(Game.camera.View * Game.camera.Projection);</div><div> currentEffect.Parameters["xTexture"].SetValue(skyBoxTextures[i]);</div><div> }</div><div><br /></div><div> for (int i = 0; i < skyBoxModel.Meshes.Count; i++)</div><div> {</div><div> skyBoxModel.Meshes[i].Draw();</div><div> }</div><div> }</div><div> }</div><div>}</div><div><br /></div><div> By implementing these changes, the SkyBox class should perform better and be more efficient in rendering the skybox in your XNA game. Remember that performance improvements might vary depending on the specific context and use case of your game. Always test and profile your code to identify further potential optimizations. We have optimized the code further by reducing redundant calculations.</div></div><div><br /></div><div><br /><b><span style="color: #6fa8dc;">How I optimized the TriangleMeshObject Class for better performance</span></b><br /><br /><div>Here is the older TriangleMeshObject source code: </div><div>using System;</div><div>using System.Collections.Generic;</div><div>using System.Text;</div><div>using Microsoft.Xna.Framework.Graphics;</div><div>using Microsoft.Xna.Framework;</div><div>using JigLibX.Geometry;</div><div>using JigLibX.Physics;</div><div>using JigLibX.Collision;</div><div><br /></div><div>namespace JiggleGame.PhysicObjects</div><div>{</div><div> class TriangleMeshObject : PhysicObject</div><div> {</div><div> TriangleMesh triangleMesh;</div><div> Matrix xform;</div><div> Game game;</div><div><br /></div><div> public TriangleMeshObject(Game game, Model model, Matrix orientation, Vector3 position)</div><div> : base(game, model)</div><div> {</div><div> body = new Body();</div><div> collision = new CollisionSkin(null);</div><div><br /></div><div> triangleMesh = new TriangleMesh();</div><div><br /></div><div> List<Vector3> vertexList = new List<Vector3>();</div><div> List<TriangleVertexIndices> indexList = new List<TriangleVertexIndices>();</div><div><br /></div><div> ExtractData(vertexList, indexList, model);</div><div><br /></div><div> triangleMesh.CreateMesh(vertexList, indexList, 4, 1.0f);</div><div> collision.AddPrimitive(triangleMesh, new MaterialProperties(0.8f, 0.7f, 0.6f));</div><div> PhysicsSystem.CurrentPhysicsSystem.CollisionSystem.AddCollisionSkin(collision);</div><div><br /></div><div> // Transform</div><div> collision.ApplyLocalTransform(new JigLibX.Math.Transform(position, orientation));</div><div><br /></div><div> // we also need to move this dummy, so the object is *rendered* at the correct positiob</div><div> //body.MoveTo(position, orientation);</div><div> this.body.CollisionSkin = this.collision;</div><div><br /></div><div> }</div><div><br /></div><div><br /></div><div> /// <summary></div><div> /// Helper Method to get the vertex and index List from the model.</div><div> /// </summary></div><div> /// <param name="vertices"></param></div><div> /// <param name="indices"></param></div><div> /// <param name="model"></param></div><div> public void ExtractData(List<Vector3> vertices, List<TriangleVertexIndices> indices, Model model)</div><div> {</div><div> Matrix[] bones_ = new Matrix[model.Bones.Count];</div><div> model.CopyAbsoluteBoneTransformsTo(bones_);</div><div> foreach (ModelMesh mm in model.Meshes)</div><div> {</div><div> Game.GraphicsDevice.RasterizerState = RasterizerState.CullNone;</div><div><br /></div><div> xform = bones_[mm.ParentBone.Index];</div><div> foreach (ModelMeshPart mmp in mm.MeshParts)</div><div> {</div><div> int offset = vertices.Count;</div><div> Vector3[] a = new Vector3[mmp.NumVertices];</div><div><br /></div><div> int vertexStride = mmp.VertexBuffer.VertexDeclaration.VertexStride;</div><div> mmp.VertexBuffer.GetData<Vector3>(mmp.VertexOffset * vertexStride,</div><div> a, 0, mmp.NumVertices, vertexStride);</div><div> //mm.VertexBuffer.GetData<Vector3>(mmp.StreamOffset + mmp.BaseVertex * mmp.VertexStride,</div><div> // a, 0, mmp.NumVertices, mmp.VertexStride);</div><div> for (int i = 0; i != a.Length; ++i)</div><div> Vector3.Transform(ref a[i], ref xform, out a[i]);</div><div> vertices.AddRange(a);</div><div><br /></div><div> for (int i = 0; i < a.Length; i++) vertices.Add(new Vector3(a[i].X, a[i].Y, a[i].Z)); // new</div><div> if (mmp.IndexBuffer.IndexElementSize != IndexElementSize.SixteenBits)</div><div> throw new Exception(</div><div> String.Format("Model uses 32-bit indices, which are not supported."));</div><div> short[] s = new short[mmp.PrimitiveCount * 3];</div><div> //mm.IndexBuffer.GetData<short>(mmp.StartIndex * 2, s, 0, mmp.PrimitiveCount * 3);</div><div> mmp.IndexBuffer.GetData<short>(mmp.StartIndex * 2, s, 0, mmp.PrimitiveCount * 3);</div><div> JigLibX.Geometry.TriangleVertexIndices[] tvi = new JigLibX.Geometry.TriangleVertexIndices[mmp.PrimitiveCount];</div><div> for (int i = 0; i != tvi.Length; ++i)</div><div> {</div><div> tvi[i].I0 = s[i * 3 + 2] + offset;</div><div> tvi[i].I1 = s[i * 3 + 1] + offset;</div><div> tvi[i].I2 = s[i * 3 + 0] + offset;</div><div> }</div><div> indices.AddRange(tvi);</div><div> }</div><div> }</div><div> }</div><div><br /></div><div><br /></div><div> public override void ApplyEffects(BasicEffect effect)</div><div> {</div><div> //this.game.GraphicsDevice.RasterizerState = RasterizerState.CullNone; // Helps displays the roads and gun in full with this, just have to fix color of wheels</div><div> //effect.EnableDefaultLighting();</div><div> //effect.SpecularPower = 5;</div><div> //effect.DiffuseColor = new Vector3(5.8f);</div><div> //effect.AmbientLightColor = new Vector3(1f, 0, 0);</div><div><br /></div><div> }</div><div><br /></div><div> public void ApplyAdvancedEffects(Effect effect)</div><div> {</div><div> foreach (ModelMesh mesh in model.Meshes)</div><div> {</div><div><br /></div><div> foreach (ModelMeshPart part in mesh.MeshParts)</div><div> {</div><div> //part.Effect = effect;</div><div><br /></div><div> }</div><div> }</div><div> }</div><div> }</div><div>}<br /><br /> Optimizing code involves various aspects, including minimizing redundant computations, reducing memory allocations, and improving code structure. Here are some steps I took to optimize the code for better performance:<br /><br /><div><b><span style="color: #93c47d;">1.) Avoid Repeated Transformations</span>:</b></div><div> The <b>Vector3.Transform</b> operation is applied twice in a loop. You can calculate the transformed vertex and reuse it directly, avoiding the redundant computation.<br /><br /><div>Vector3 transformedVertex;</div><div>for (int i = 0; i < a.Length; ++i)</div><div>{</div><div> Vector3.Transform(ref a[i], ref xform, out transformedVertex);</div><div> vertices.Add(transformedVertex);</div><div>}</div><div><br /></div><br /><div><b><span style="color: #93c47d;">2.) Memory Allocation</span>:</b></div><div> The following lines are allocating additional memory for each vertex, which can be avoided since it's duplicating data:<br /><br /><div>for (int i = 0; i < a.Length; i++)</div><div> vertices.Add(new Vector3(a[i].X, a[i].Y, a[i].Z));</div></div><div><br /></div><div>You can remove this block since it's already covered by the previous loop that adds transformed vertices.</div><div><br /></div><div><br /></div><div><b><span style="color: #93c47d;">3.) Minimize GraphicsDevice Calls</span></b>:</div><div> The GraphicsDevice's state changes (RasterizerState settings) inside the ExtractData method might be better suited outside of this method, ideally during the initialization or setup phase.</div><div><br /></div><div><br /></div><div><b><span style="color: #93c47d;">4.) Use foreach Loop for Vertex Extraction</span></b>:</div><div> Instead of using a for loop to extract vertices, consider using a foreach loop, which is generally more readable and safer when working with collections.<br /><br /><div>foreach (ModelMesh mm in model.Meshes)</div><div>{</div><div> // ...</div><div> foreach (ModelMeshPart mmp in mm.MeshParts)</div><div> {</div><div> // ...</div><div> mmp.VertexBuffer.GetData<Vector3>(mmp.VertexOffset * vertexStride, a, 0, mmp.NumVertices, vertexStride);</div><div><br /></div><div> foreach (Vector3 vertex in a)</div><div> {</div><div> Vector3.Transform(ref vertex, ref xform, out transformedVertex);</div><div> vertices.Add(transformedVertex);</div><div> }</div><div> // ...</div><div> }</div><div> // ...</div><div>}</div></div></div></div><div><br /></div><div><br /><div><b><span style="color: #93c47d;">5.) Avoid Exception Throwing</span>:</b></div><div> Throwing exceptions in performance-critical paths can negatively impact performance. Consider using conditional checks instead of throwing exceptions.</div><div><br /></div><div><br /></div><div><b><span style="color: #93c47d;">6.) Reduce Matrix Array Access</span>:</b></div><div> The code frequently accesses the bones_ array using mm.ParentBone.Index. You can store the parent bone index in a variable to reduce repeated array access.</div><div><br /></div><div><br /></div><div><b><span style="color: #93c47d;">7.) Batch Operations</span>:</b></div><div> Consider using batch operations and parallel processing where applicable to optimize certain tasks. However, be cautious about multithreading when working with graphics APIs.</div></div><div><br /></div><div><br /></div>Here is the new code in full: <br /><br /><div>using System;</div><div>using System.Collections.Generic;</div><div>using Microsoft.Xna.Framework;</div><div>using Microsoft.Xna.Framework.Graphics;</div><div>using JigLibX.Geometry;</div><div>using JigLibX.Physics;</div><div>using JigLibX.Collision;</div><div><br /></div><div>namespace JiggleGame.PhysicObjects</div><div>{</div><div> class TriangleMeshObject : PhysicObject</div><div> {</div><div> TriangleMesh triangleMesh;</div><div> Game game;</div><div><br /></div><div> public TriangleMeshObject(Game game, Model model, Matrix orientation, Vector3 position)</div><div> : base(game, model)</div><div> {</div><div> body = new Body();</div><div> collision = new CollisionSkin(null);</div><div><br /></div><div> triangleMesh = new TriangleMesh();</div><div><br /></div><div> List<Vector3> vertexList = new List<Vector3>();</div><div> List<TriangleVertexIndices> indexList = new List<TriangleVertexIndices>();</div><div><br /></div><div> ExtractData(vertexList, indexList, model);</div><div><br /></div><div> triangleMesh.CreateMesh(vertexList, indexList, 4, 1.0f);</div><div> collision.AddPrimitive(triangleMesh, new MaterialProperties(0.8f, 0.7f, 0.6f));</div><div> PhysicsSystem.CurrentPhysicsSystem.CollisionSystem.AddCollisionSkin(collision);</div><div><br /></div><div> // Transform</div><div> collision.ApplyLocalTransform(new JigLibX.Math.Transform(position, orientation));</div><div><br /></div><div> this.body.CollisionSkin = this.collision;</div><div> }</div><div><br /></div><div> public void ExtractData(List<Vector3> vertices, List<TriangleVertexIndices> indices, Model model)</div><div> {</div><div> Matrix[] bones_ = new Matrix[model.Bones.Count];</div><div> model.CopyAbsoluteBoneTransformsTo(bones_);</div><div><br /></div><div> foreach (ModelMesh mm in model.Meshes)</div><div> {</div><div> Matrix xform = bones_[mm.ParentBone.Index];</div><div><br /></div><div> foreach (ModelMeshPart mmp in mm.MeshParts)</div><div> {</div><div> int offset = vertices.Count;</div><div> Vector3[] a = new Vector3[mmp.NumVertices];</div><div><br /></div><div> int vertexStride = mmp.VertexBuffer.VertexDeclaration.VertexStride;</div><div> mmp.VertexBuffer.GetData<Vector3>(mmp.VertexOffset * vertexStride, a, 0, mmp.NumVertices, vertexStride);</div><div><br /></div><div> Vector3 transformedVertex;</div><div> for (int i = 0; i < a.Length; ++i)</div><div> {</div><div> Vector3.Transform(ref a[i], ref xform, out transformedVertex);</div><div> vertices.Add(transformedVertex);</div><div> }</div><div><br /></div><div> if (mmp.IndexBuffer.IndexElementSize != IndexElementSize.SixteenBits)</div><div> {</div><div> throw new Exception("Model uses 32-bit indices, which are not supported.");</div><div> }</div><div><br /></div><div> short[] s = new short[mmp.PrimitiveCount * 3];</div><div> mmp.IndexBuffer.GetData<short>(mmp.StartIndex * 2, s, 0, mmp.PrimitiveCount * 3);</div><div><br /></div><div> TriangleVertexIndices[] tvi = new TriangleVertexIndices[mmp.PrimitiveCount];</div><div> for (int i = 0; i < tvi.Length; ++i)</div><div> {</div><div> tvi[i].I0 = s[i * 3 + 2] + offset;</div><div> tvi[i].I1 = s[i * 3 + 1] + offset;</div><div> tvi[i].I2 = s[i * 3 + 0] + offset;</div><div> }</div><div><br /></div><div> indices.AddRange(tvi);</div><div> }</div><div> }</div><div> }</div><div><br /></div><div> // Other methods...</div><div><br /></div><div> public override void ApplyEffects(BasicEffect effect)</div><div> {</div><div> // Apply effects if needed</div><div> }</div><div><br /></div><div> public void ApplyAdvancedEffects(Effect effect)</div><div> {</div><div> // Apply advanced effects if needed</div><div> }</div><div> }</div><div>}</div></div><div><br /></div><div><br /></div><div><br /></div><div><b><span style="color: #6fa8dc;">How I Optimized the PhysicObject Class for Better Performance</span></b><br /><br />Original Source Code: <br /><div>using System;</div><div>using System.Collections.Generic;</div><div>using System.Text;</div><div><br /></div><div>using Microsoft.Xna.Framework.Graphics;</div><div>using Microsoft.Xna.Framework;</div><div><br /></div><div>using JigLibX.Physics;</div><div>using JigLibX.Collision;</div><div>using JigLibX.Geometry;</div><div><br /></div><div>namespace JiggleGame.PhysicObjects</div><div>{</div><div><br /></div><div> /// <summary></div><div> /// Helps to combine the physics with the graphics.</div><div> /// </summary></div><div> public abstract class PhysicObject : DrawableGameComponent</div><div> {</div><div><br /></div><div> protected Body body;</div><div> protected CollisionSkin collision;</div><div><br /></div><div> protected Model model;</div><div> protected Vector3 color;</div><div><br /></div><div> protected Vector3 scale = Vector3.One;</div><div><br /></div><div> public Body PhysicsBody{get { return body; }}</div><div> public CollisionSkin PhysicsSkin{ get { return collision; }}</div><div><br /></div><div> protected static Random random = new Random();</div><div><br /></div><div> public PhysicObject(Game game,Model model) : base(game)</div><div> {</div><div> this.model = model;</div><div> color = new Vector3(random.Next(255), random.Next(255), random.Next(255));</div><div> color /= 255.0f;</div><div> }</div><div><br /></div><div> public PhysicObject(Game game)</div><div> : base(game)</div><div> {</div><div> this.model = null;</div><div> color = new Vector3(random.Next(255), random.Next(255), random.Next(255));</div><div> color /= 255.0f;</div><div> }</div><div><br /></div><div> protected Vector3 SetMass(float mass)</div><div> {</div><div> PrimitiveProperties primitiveProperties =</div><div> new PrimitiveProperties(PrimitiveProperties.MassDistributionEnum.Solid, PrimitiveProperties.MassTypeEnum.Density, mass);</div><div><br /></div><div> float junk; Vector3 com; Matrix it, itCoM;</div><div><br /></div><div> collision.GetMassProperties(primitiveProperties, out junk, out com, out it, out itCoM);</div><div> body.BodyInertia = itCoM;</div><div> body.Mass = junk;</div><div><br /></div><div> return com;</div><div> }</div><div> Matrix[] boneTransforms = null;</div><div> int boneCount = 0;</div><div><br /></div><div> public abstract void ApplyEffects(BasicEffect effect);</div><div> public override void Draw(GameTime gameTime)</div><div> {</div><div> if (model != null)</div><div> {</div><div> if (boneTransforms == null || boneCount != model.Bones.Count)</div><div> {</div><div> boneTransforms = new Matrix[model.Bones.Count];</div><div> boneCount = model.Bones.Count;</div><div> }</div><div><br /></div><div> model.CopyAbsoluteBoneTransformsTo(boneTransforms);</div><div><br /></div><div> Camera camera = ((JiggleGame)this.Game).Camera;</div><div> foreach (ModelMesh mesh in model.Meshes)</div><div> {</div><div> foreach (BasicEffect effect in mesh.Effects)</div><div> {</div><div><br /></div><div> // the body has an orientation but also the primitives in the collision skin</div><div> // owned by the body can be rotated!</div><div> if(body.CollisionSkin != null)</div><div> effect.World = boneTransforms[mesh.ParentBone.Index] * Matrix.CreateScale(scale) * body.CollisionSkin.GetPrimitiveLocal(0).Transform.Orientation * body.Orientation * Matrix.CreateTranslation(body.Position);</div><div> else</div><div> effect.World = boneTransforms[mesh.ParentBone.Index] * Matrix.CreateScale(scale) * body.Orientation * Matrix.CreateTranslation(body.Position);</div><div> </div><div> effect.View = camera.View;</div><div> effect.Projection = camera.Projection;</div><div><br /></div><div> ApplyEffects(effect);</div><div><br /></div><div> //if (!this.PhysicsBody.IsActive)</div><div> // effect.Alpha = 0.4f;</div><div> //else</div><div> // effect.Alpha = 1.0f;</div><div><br /></div><div><br /></div><div> effect.EnableDefaultLighting();</div><div> effect.PreferPerPixelLighting = true;</div><div> }</div><div> mesh.Draw();</div><div> }</div><div><br /></div><div> }</div><div><br /></div><div> /* if (((JiggleGame)this.Game).DebugDrawer.Enabled)</div><div> {</div><div><br /></div><div> wf = collision.GetLocalSkinWireframe();</div><div><br /></div><div> // if the collision skin was also added to the body</div><div> // we have to transform the skin wireframe to the body space</div><div> if (body.CollisionSkin != null)</div><div> {</div><div> body.TransformWireframe(wf);</div><div> }</div><div><br /></div><div> // ((JiggleGame)this.Game).DebugDrawer.DrawShape(wf);</div><div> }</div><div> */</div><div><br /></div><div> // base.Draw(gameTime);</div><div> }</div><div><br /></div><div> VertexPositionColor[] wf;</div><div><br /></div><div> }</div><div>}</div><div><br /></div><div>To improve the performance of the code give above, we can make several optimizations. Here's the modified version with explanations for each change:<br /><br /><div>Changes made:</div><div><br /></div><div>1. Replaced the multiplication by '<b>255.0f'</b> with a division by '<b>255.0f'</b> to directly obtain the normalized color vector.<br /><br /></div><div>2. Used a ternary expression to determine the orientation transformation based on whether '<b>body.CollisionSkin'</b> is null or not.<br /><br /></div><div>3. Moved the creation of the '<b>worldMatrix'</b> outside the inner loop to avoid recompilation in each iteration.<br /><br /></div><div>4. Removed the commented-out code that was not being used.<br /><br /></div><div>5. Simplified the property getter syntax.<br /><br /></div><div>6. Removed unnecessary field '<b>wf'</b>, which was declared but not used.<br /><br /><br /></div>New Code: <br /><br /><div>using System;</div><div>using Microsoft.Xna.Framework;</div><div>using Microsoft.Xna.Framework.Graphics;</div><div>using JigLibX.Physics;</div><div>using JigLibX.Collision;</div><div>using JigLibX.Geometry;</div><div><br /></div><div>namespace JiggleGame.PhysicObjects</div><div>{</div><div> public abstract class PhysicObject : DrawableGameComponent</div><div> {</div><div> protected Body body;</div><div> protected CollisionSkin collision;</div><div> protected Model model;</div><div> protected Vector3 color;</div><div> protected Vector3 scale = Vector3.One;</div><div><br /></div><div> public Body PhysicsBody => body;</div><div> public CollisionSkin PhysicsSkin => collision;</div><div><br /></div><div> protected static readonly Random random = new Random();</div><div><br /></div><div> private Matrix[] boneTransforms;</div><div> private int boneCount;</div><div><br /></div><div> public PhysicObject(Game game, Model model) : base(game)</div><div> {</div><div> this.model = model;</div><div> color = new Vector3(random.Next(256), random.Next(256), random.Next(256)) / 255.0f;</div><div> }</div><div><br /></div><div> public PhysicObject(Game game) : base(game)</div><div> {</div><div> model = null;</div><div> color = new Vector3(random.Next(256), random.Next(256), random.Next(256)) / 255.0f;</div><div> }</div><div><br /></div><div> protected Vector3 SetMass(float mass)</div><div> {</div><div> PrimitiveProperties primitiveProperties =</div><div> new PrimitiveProperties(PrimitiveProperties.MassDistributionEnum.Solid, PrimitiveProperties.MassTypeEnum.Density, mass);</div><div><br /></div><div> float junk; Vector3 com; Matrix it, itCoM;</div><div><br /></div><div> collision.GetMassProperties(primitiveProperties, out junk, out com, out it, out itCoM);</div><div> body.BodyInertia = itCoM;</div><div> body.Mass = junk;</div><div><br /></div><div> return com;</div><div> }</div><div><br /></div><div> public abstract void ApplyEffects(BasicEffect effect);</div><div><br /></div><div> public override void Draw(GameTime gameTime)</div><div> {</div><div> if (model != null)</div><div> {</div><div> if (boneTransforms == null || boneCount != model.Bones.Count)</div><div> {</div><div> boneTransforms = new Matrix[model.Bones.Count];</div><div> boneCount = model.Bones.Count;</div><div> }</div><div><br /></div><div> model.CopyAbsoluteBoneTransformsTo(boneTransforms);</div><div><br /></div><div> var camera = ((JiggleGame)Game).Camera;</div><div> foreach (var mesh in model.Meshes)</div><div> {</div><div> foreach (BasicEffect effect in mesh.Effects)</div><div> {</div><div> var worldMatrix = boneTransforms[mesh.ParentBone.Index] *</div><div> Matrix.CreateScale(scale) *</div><div> (body.CollisionSkin != null</div><div> ? body.CollisionSkin.GetPrimitiveLocal(0).Transform.Orientation</div><div> : Matrix.Identity) *</div><div> body.Orientation *</div><div> Matrix.CreateTranslation(body.Position);</div><div> effect.World = worldMatrix;</div><div> effect.View = camera.View;</div><div> effect.Projection = camera.Projection;</div><div><br /></div><div> ApplyEffects(effect);</div><div><br /></div><div> effect.EnableDefaultLighting();</div><div> effect.PreferPerPixelLighting = true;</div><div> }</div><div> mesh.Draw();</div><div> }</div><div> }</div><div><br /></div><div> base.Draw(gameTime);</div><div> }</div><div> }</div><div>}</div></div><div><br /></div><div><br /></div><br /></div><div><b><span style="color: #6fa8dc;">How I Optimized the JigLibX PhysicsCollision Class for Better Performance</span></b><br /><br /><div>Original Source Code: </div><div>#region Using Statements</div><div>using System;</div><div>using System.Collections.Generic;</div><div>using System.Text;</div><div><br /></div><div>using Microsoft.Xna.Framework;</div><div>using JigLibX.Collision;</div><div>#endregion</div><div><br /></div><div>namespace JigLibX.Physics</div><div>{</div><div> #region CollisionIsland</div><div> /// <summary></div><div> /// Class CollisionIsland</div><div> /// </summary></div><div> public class CollisionIsland : List<Body></div><div> {</div><div> /// <summary></div><div> /// Constructor</div><div> /// </summary></div><div> public CollisionIsland()</div><div> : base(64)</div><div> {</div><div> }</div><div> /// <summary></div><div> /// Empry CollisionIsland</div><div> /// </summary></div><div> private static CollisionIsland empty = new CollisionIsland();</div><div> /// <summary></div><div> /// Gets empty</div><div> /// </summary></div><div> public static CollisionIsland Empty { get { return empty; } }</div><div><br /></div><div> /// <summary></div><div> /// WantsDeactivation</div><div> /// </summary></div><div> /// <param name="dt"></param></div><div> /// <returns>bool</returns></div><div> public bool WantsDeactivation(float dt)</div><div> {</div><div> for (int i = 0; i < this.Count; i++)</div><div> if (this[i].GetShouldBeActive()) return false;</div><div> return true;</div><div> }</div><div><br /></div><div> /// <summary></div><div> /// Deactivate</div><div> /// </summary></div><div> public void Deactivate()</div><div> {</div><div> int count = this.Count;</div><div> for (int i = 0; i < count; i++) this[i].SetInactive();</div><div> }</div><div><br /></div><div> /// <summary></div><div> /// Activate</div><div> /// </summary></div><div> public void Activate()</div><div> {</div><div> int count = this.Count;</div><div> for (int i = 0; i < count; i++) this[i].SetActive();</div><div> }</div><div> }</div><div> #endregion</div><div><br /></div><div> #region BasicCollisionFunctor</div><div><br /></div><div> /// <summary></div><div> /// Derived from the CollisionFunctor class. The BasicCollisionFunctor can be passed to</div><div> /// CollisionSystem.DetectAllCollision method and gets called for every collision found. </div><div> /// The collisions get added to a list.</div><div> /// </summary></div><div> public class BasicCollisionFunctor : CollisionFunctor</div><div> {</div><div><br /></div><div> private List<CollisionInfo> colls;</div><div><br /></div><div> /// <summary></div><div> /// Constructor of BasicCollisionFunctor.</div><div> /// </summary></div><div> /// <param name="colls">This list gets filled with collisionInfo entries.</param></div><div> public BasicCollisionFunctor(List<CollisionInfo> colls)</div><div> {</div><div> this.colls = colls;</div><div> }</div><div><br /></div><div> /// <summary></div><div> /// CollisionNotify gets called by the CollisionSystem each time a</div><div> /// Collision is detected.</div><div> /// </summary></div><div> /// <param name="collDetectInfo"></param></div><div> /// <param name="dirToBody0"></param></div><div> /// <param name="pointInfos"></param></div><div> /// <param name="numCollPts"></param></div><div> public override unsafe void CollisionNotify(ref CollDetectInfo collDetectInfo, ref Vector3 dirToBody0, SmallCollPointInfo* pointInfos, int numCollPts)</div><div> {</div><div> CollisionInfo info;</div><div> // shortcuts to save typing it over and over</div><div> CollisionSkin skin0 = collDetectInfo.Skin0;</div><div> CollisionSkin skin1 = collDetectInfo.Skin1;</div><div><br /></div><div> // if more than one point, add another that is in the middle - collision</div><div><br /></div><div> if ((skin0 != null) && (skin0.Owner != null))</div><div> { </div><div> // if either skin say don't generate contact points, then we don't</div><div> bool generateContactPoints = skin0.OnCollisionEvent(skin0,skin1);</div><div> if (skin1 != null)</div><div> {</div><div> generateContactPoints &= skin1.OnCollisionEvent(skin1,skin0);</div><div> }</div><div><br /></div><div> if (generateContactPoints)</div><div> {</div><div> info = CollisionInfo.GetCollisionInfo(collDetectInfo, dirToBody0, pointInfos, numCollPts);</div><div> colls.Add(info);</div><div> skin0.Collisions.Add(info);</div><div><br /></div><div> if ((skin1 != null) && (skin1.Owner != null))</div><div> skin1.Collisions.Add(info);</div><div> }</div><div> }</div><div> else if ((skin1 != null) && (skin1.Owner != null))</div><div> {</div><div> // if either skin say don't generate contact points, then we don't</div><div> bool generateContactPoints = skin1.OnCollisionEvent(skin1,skin0);</div><div> if (skin0 != null)</div><div> {</div><div> generateContactPoints &= skin0.OnCollisionEvent(skin0,skin1);</div><div> }</div><div><br /></div><div> if (generateContactPoints)</div><div> {</div><div> info = CollisionInfo.GetCollisionInfo(collDetectInfo, -dirToBody0, pointInfos, numCollPts);</div><div> colls.Add(info);</div><div> skin1.Collisions.Add(info);</div><div> if ((skin0 != null) && (skin0.Owner != null))</div><div> skin0.Collisions.Add(info);</div><div> }</div><div> }</div><div> else</div><div> System.Diagnostics.Debug.WriteLine("Collision detected with both skin bodies null.");</div><div> }</div><div> }</div><div><br /></div><div> #endregion</div><div><br /></div><div> #region FrozenCollisionPredicate</div><div><br /></div><div> /// <summary></div><div> /// Derived from CollisionSkinPredicate2. A SkinPredicate2 which can be passed</div><div> /// to CollisionSystem.DetectCollisions. Only active skin owners get considered.</div><div> /// </summary></div><div> public class FrozenCollisionPredicate : CollisionSkinPredicate2</div><div> {</div><div><br /></div><div> private Body body;</div><div><br /></div><div><br /></div><div> /// <summary></div><div> /// Constructor of FrozenCollision Predicate.</div><div> /// </summary></div><div> /// <param name="body">The body itself doesn't get checked.</param></div><div> public FrozenCollisionPredicate(Body body)</div><div> {</div><div> this.body = body;</div><div> }</div><div><br /></div><div> /// <summary></div><div> /// Considers two skins and returns true if their bodies aren't frozen.</div><div> /// </summary></div><div> /// <param name="skin0">The first skin of the pair of skins which should be checked.</param></div><div> /// <param name="skin1">The second skin of the pair of skins which should be checked.</param></div><div> /// <returns>Returns true if the skinPair owners are active otherwise false.</returns></div><div> public override bool ConsiderSkinPair(CollisionSkin skin0, CollisionSkin skin1)</div><div> {</div><div> if ((skin0.Owner != null) && (skin0.Owner != body))</div><div> if (!skin0.Owner.IsActive) return true;</div><div><br /></div><div> if ((skin1.Owner != null) && (skin1.Owner != body))</div><div> if (!skin1.Owner.IsActive) return true;</div><div><br /></div><div> return false;</div><div> }</div><div> }</div><div> #endregion</div><div><br /></div><div>}<br /><br /></div></div><div><br /></div><div> To optimize the provided code above for better performance, I applied several optimizations and practices. Here are the steps:<br /><br /><div><span style="color: #93c47d;"><b>1.)</b> </span><b><span style="color: #93c47d;">Remove Unused Using Statements</span>:</b> Remove any using statements that are not actually used in the code to reduce unnecessary dependencies.</div><div><br /></div><div><b><span style="color: #93c47d;">2.) Local Variable Caching</span>:</b> Cache frequently used variables to reduce repeated lookups.</div><div><br /></div><div><b><span style="color: #93c47d;">3.) Inline Short Methods</span>:</b> Consider inlining very short methods that are called frequently, as method calls have some overhead.</div><div><br /></div><div><b><span style="color: #93c47d;">4.) Use foreach Loop</span>:</b> Use foreach loops instead of for loops for iterating through collections when you don't need the index.</div><div><br /></div><div><b><span style="color: #93c47d;">5.) Use Structs for Small Data</span>:</b> Consider using structs instead of classes for small data structures like Vector3 and CollisionInfo to reduce memory allocation overhead.</div><div><br /></div><div><b><span style="color: #93c47d;">6.) Minimize Object Instantiation</span>:</b> Reduce object instantiation and memory allocation where possible.</div><div><br /></div><div><b><span style="color: #93c47d;">7.) Method Parameter Optimization</span>: </b>Pass parameters by reference where appropriate to avoid unnecessary copying.</div><div><br /></div><div><b><span style="color: #93c47d;">8.) Code Commenting</span></b>: Remove unnecessary comments that don't add value to the understanding of the code.</div></div><div><br /></div><div><br /></div><div> An optimized version of the code with the above steps applied below. Also in this version, the '<b>info'</b> variable is initialized to '<b>null'</b> at the beginning of the <b>'generateContactPoints'</b> block. This should ensure that it's properly assigned within either of the conditional blocks before it's used. <br /><br />Here's the new code:</div><div><br /><div>using System.Collections.Generic;</div><div>using Microsoft.Xna.Framework;</div><div>using JigLibX.Collision;</div><div><br /></div><div>namespace JigLibX.Physics</div><div>{</div><div> public class CollisionIsland : List<Body></div><div> {</div><div> private static readonly CollisionIsland empty = new CollisionIsland();</div><div> public static CollisionIsland Empty => empty;</div><div><br /></div><div> public CollisionIsland() : base(64) { }</div><div><br /></div><div> public bool WantsDeactivation(float dt)</div><div> {</div><div> foreach (var body in this)</div><div> {</div><div> if (body.GetShouldBeActive()) return false;</div><div> }</div><div> return true;</div><div> }</div><div><br /></div><div> public void Deactivate()</div><div> {</div><div> foreach (var body in this)</div><div> {</div><div> body.SetInactive();</div><div> }</div><div> }</div><div><br /></div><div> public void Activate()</div><div> {</div><div> foreach (var body in this)</div><div> {</div><div> body.SetActive();</div><div> }</div><div> }</div><div> }</div><div><br /></div><div> public class BasicCollisionFunctor : CollisionFunctor</div><div> {</div><div> private readonly List<CollisionInfo> colls;</div><div><br /></div><div> public BasicCollisionFunctor(List<CollisionInfo> colls)</div><div> {</div><div> this.colls = colls;</div><div> }</div><div><br /></div><div> public override unsafe void CollisionNotify(ref CollDetectInfo collDetectInfo, ref Vector3 dirToBody0, SmallCollPointInfo* pointInfos, int numCollPts)</div><div> {</div><div> var skin0 = collDetectInfo.Skin0;</div><div> var skin1 = collDetectInfo.Skin1;</div><div> bool generateContactPoints = false;</div><div> CollisionInfo info;</div><div><br /></div><div> if (skin0 != null && skin0.Owner != null)</div><div> {</div><div> generateContactPoints = skin0.OnCollisionEvent(skin0, skin1);</div><div> if (skin1 != null)</div><div> {</div><div> generateContactPoints &= skin1.OnCollisionEvent(skin1, skin0);</div><div> }</div><div> }</div><div> else if (skin1 != null && skin1.Owner != null)</div><div> {</div><div> generateContactPoints = skin1.OnCollisionEvent(skin1, skin0);</div><div> if (skin0 != null)</div><div> {</div><div> generateContactPoints &= skin0.OnCollisionEvent(skin0, skin1);</div><div> }</div><div> }</div><div><br /></div><div> if (generateContactPoints)</div><div> {</div><div> info = null;</div><div> if (skin0 != null)</div><div> {</div><div> info = CollisionInfo.GetCollisionInfo(collDetectInfo, dirToBody0, pointInfos, numCollPts);</div><div> colls.Add(info);</div><div> skin0.Collisions.Add(info);</div><div> }</div><div><br /></div><div> if (skin1 != null && skin1.Owner != null)</div><div> {</div><div> if (info == null)</div><div> {</div><div> info = CollisionInfo.GetCollisionInfo(collDetectInfo, -dirToBody0, pointInfos, numCollPts);</div><div> colls.Add(info);</div><div> }</div><div> skin1.Collisions.Add(info);</div><div> }</div><div> }</div><div> else</div><div> {</div><div> System.Diagnostics.Debug.WriteLine("Collision detected with both skin bodies null.");</div><div> }</div><div><br /></div><div> }</div><div> }</div><div><br /></div><div> public class FrozenCollisionPredicate : CollisionSkinPredicate2</div><div> {</div><div> private readonly Body body;</div><div><br /></div><div> public FrozenCollisionPredicate(Body body)</div><div> {</div><div> this.body = body;</div><div> }</div><div><br /></div><div> public override bool ConsiderSkinPair(CollisionSkin skin0, CollisionSkin skin1)</div><div> {</div><div> if (skin0.Owner != null && skin0.Owner != body && !skin0.Owner.IsActive)</div><div> return true;</div><div><br /></div><div> if (skin1.Owner != null && skin1.Owner != body && !skin1.Owner.IsActive)</div><div> return true;</div><div><br /></div><div> return false;</div><div> }</div><div> }</div><div>}</div></div><div><br /></div></div>Jordon McClainhttp://www.blogger.com/profile/18342097908172252205noreply@blogger.com2tag:blogger.com,1999:blog-3257117917071262914.post-33144103656083533112023-07-14T08:24:00.014-07:002023-07-21T05:15:10.491-07:0088.) Terminal Map Remake Early Prototype<div style="text-align: center;"><iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen="" frameborder="0" height="351" src="https://www.youtube.com/embed/DAJznbz2HHc" title="YouTube video player" width="624"></iframe></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: left;"> Today, we embark on an exciting journey to recreate one of the most iconic multiplayer maps in gaming history: Terminal from Call of Duty: Modern Warfare 2. My goal is to rebuild the map from scratch in the Cyclone Game Engine using the XNA framework and MonoGame, alongside a couple of powerful tools that will enhance our development process. I started the day by studying the original map's layout, textures, and gameplay mechanics. Immersing myself in the details of Terminal, I carefully analyzed the paths, chokepoints, and strategic areas that made the map so memorable. Armed with this knowledge, I brainstormed ideas on how to translate those elements into the engine, ensuring I captured the essence of the original map while also infusing some of my own creative touches.</div><div style="text-align: left;"><br /></div><div style="text-align: left;"><br /></div>
<div style="text-align: center;"><a href="https://www.indiedb.com/engines/cyclone-engine/images/terminal-remake-devlog-v115" target="_blank" title="Terminal Remake Devlog v1 - Indie DB"><img alt="Terminal Remake Devlog v1" src="https://media.indiedb.com/cache/images/engines/1/1/427/thumb_620x2000/Terminal_1.jpg" /></a></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: left;"> To bring life to our character, I turned to Mixamo, a fantastic tool for character animation. With Mixamo, I was able to access a vast library of pre-made character animations and easily apply them to my in-game model. This saved me a tremendous amount of time and effort, allowing me to focus more on other aspects of the game development process. Jiggle Library-X (JigLibX) is utilized for the physics. Models from the scene are being extracted and and tested for collision.</div><div style="text-align: left;"><br /></div><div style="text-align: center;"><a href="https://www.indiedb.com/engines/cyclone-engine/images/terminal-map-remake-screenshots-v2" target="_blank" title="Terminal Map Remake Screenshots V2 - Indie DB"><img alt="Terminal Map Remake Screenshots V2" src="https://media.indiedb.com/cache/images/engines/1/1/427/thumb_620x2000/T5_Collision_Skins.jpg" /></a> </div><div style="text-align: left;"><br /></div><div style="text-align: left;"> One of the biggest challenges is performance for the physics on more detailed models like in this picture above which also resulted in slowing the game's frame-rate. To fix this, I will most likely create two models; a low poly and high poly version. Low-poly models will be rendered unseen and most likely used for the models' collision physics to help with performance. The high-poly models with more detailed meshes will be visible for more pleasing visual aesthetics.In addition to leveraging Mixamo for character animation and Jiggle Library-X for physics, I also incorporated another powerful tool into our development arsenal: the XNAnimation library originally created by Bruno Evangelista. The XNAnimation library provided us with an extensive set of tools and functionalities to handle character animation within the XNA framework. This library enabled me to import and manage complex skeletal animations seamlessly. With XNAnimation, I could rig and animate our character model, ensuring fluid and realistic movements.</div><div style="text-align: left;"><br /></div><div style="text-align: left;"> One of the standout features of the XNAnimation library was its support for skeletal animation blending. This allowed me to smoothly transition between different animations, such as running, jumping, and shooting, providing a seamless and immersive experience for the players. However, animation blending is not presented in this following video. I was able to define animation states, set up animation trees, and control the blending parameters to achieve the desired results. Furthermore, the XNAnimation library offered a range of utilities for retargeting animations, which proved invaluable during my development process. I was able to transfer animations from one character model to another with varying skeletal structures, saving significant time and effort in adapting animations to different characters or variations within our game.</div><div><br /><br /><b><span style="color: #e06666;">Bone Rotation Problem</span></b></div><div> During the development process, I encountered various challenges related to character animation and camera interactions. While Mixamo proved to be a reliable tool for basic animations like walking and running, we realized that we needed additional techniques to achieve more complex actions and enhance the overall player experience. For instance, as you can see in this video, we need to address the issue of the bone moving with the camera rotation, particularly when looking up and down or aiming at a target from different positions.</div><div><br /></div><div style="text-align: center;"><a href="https://www.indiedb.com/engines/cyclone-engine/images/terminal-map-remake-screenshots-v21" target="_blank" title="Terminal Map Remake Screenshots V2 - Indie DB"><img alt="Terminal Map Remake Screenshots V2" src="https://media.indiedb.com/cache/images/engines/1/1/427/thumb_620x2000/Look_Up_Down.jpg" /></a> </div><div><br /></div><div> To fix this, I will turn to procedural animation and inverse kinematics. These techniques will allow us to dynamically adjust the character's animations and limb positions based on the player's input or environmental factors. To further enhance the character's interaction with the environment, I most likely plan to incorporate inverse kinematics into my development process. Inverse kinematics will help to prevent the player from seeing the character's body when the bones of the model rotates in first-person perspective when looking up and down. </div><div><br /></div><div> By implementing Inverse kinematics, this will enable us to precisely control the placement and movement of the character's limbs, making actions such as aiming at targets or reaching for objects appear more natural and lifelike. Whether it’s reaching for a weapon or interacting with an in-game object, an IK system in XNAnimation will help me to achieve a higher level of realism and interactivity in our games. Inverse kinematics allows us to calculate the positions and rotations of the character's joints dynamically, taking into account factors like the player's input or the position of the target in the game world. </div><div><br /></div><div> To implement procedural animation, I leveraged the power of Maya, a widely-used 3D modeling and animation software. Using Maya, I exported the animated model from Mixamo and then customized the animation rigs to accommodate the specific camera interactions I desired. By fine-tuning the rigging and adjusting bone weights, this will ensure that the character's movements responds smoothly and realistically to the player's camera rotations. <br /><br /><br /><b><span style="color: #e06666;">Problem: Black Spots Appearing on Mesh Faces</span><br /><br /></b></div><div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://www.indiedb.com/engines/cyclone-engine/images/terminal-remake-devlog-v13" style="margin-left: auto; margin-right: auto;" target="_blank" title="Terminal Remake Devlog v1 - Indie DB"><img alt="Terminal Remake Devlog v1" src="https://media.indiedb.com/cache/images/engines/1/1/427/thumb_620x2000/Terminal_5.jpg" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;"><b>Before: Dark Spots Problem Pic-1</b></td></tr></tbody></table><br /></div><div><br /></div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://www.indiedb.com/engines/cyclone-engine/images/terminal-remake-devlog-v15" style="margin-left: auto; margin-right: auto;" target="_blank" title="Terminal Remake Devlog v1 - Indie DB"><img alt="Terminal Remake Devlog v1" src="https://media.indiedb.com/cache/images/engines/1/1/427/thumb_620x2000/Terminal_7.jpg" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;"><b>Darks Spots Problem Pic-2</b></td></tr></tbody></table><div><br /></div><div><br /></div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://www.indiedb.com/engines/cyclone-engine/images/terminal-remake-devlog-v19" style="margin-left: auto; margin-right: auto;" target="_blank" title="Terminal Remake Devlog v1 - Indie DB"><img alt="Terminal Remake Devlog v1" src="https://media.indiedb.com/cache/images/engines/1/1/427/thumb_620x2000/Terminal_11.jpg" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;"><b>Dark Spots Problem Pic-3</b></td></tr></tbody></table><div style="text-align: center;"><br /></div><div> Many of the models were created using SketchUp. When imported into Maya as a .fbx file, I noticed many dark spots appearing on the faces for some reason on the models. First I tried clearing the mesh and nothing changed. Changing the texture didn't solve the problem either. Then I tried deleting a face and appending a new face at the same place which worked and made the black spots disappear. However, this was time consuming to fix all the faces by hand especially on very detailed models. The best solution was to unlock the normals of the model which removed all of the dark spots.</div><div><br /></div><div><br /></div><div><b><span style="color: #93c47d;">Solution: Unlock Normals</span></b></div><div><b><span style="color: #93c47d;"><br /></span></b></div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://www.indiedb.com/engines/cyclone-engine/images/terminal-map-remake-progress-screenshots-v23" style="margin-left: auto; margin-right: auto;" target="_blank" title="Terminal Map Remake Progress Screenshots V2 - Indie DB"><img alt="Terminal Map Remake Progress Screenshots V2" src="https://media.indiedb.com/cache/images/engines/1/1/427/thumb_620x2000/T3.jpg" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;"><b>After: Dark Spots Successfully Removed<br /><br /><br /></b></td></tr></tbody></table> <table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://www.indiedb.com/engines/cyclone-engine/images/terminal-map-remake-progress-screenshots-v2" style="margin-left: auto; margin-right: auto;" target="_blank" title="Terminal Map Remake Progress Screenshots V2 - Indie DB"><img alt="Terminal Map Remake Progress Screenshots V2" src="https://media.indiedb.com/cache/images/engines/1/1/427/thumb_620x2000/T7.jpg" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;"><b>Dark Spots Removed Pic-2<br /><br /><br /></b></td></tr></tbody></table><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://www.indiedb.com/engines/cyclone-engine/images/terminal-map-remake-progress-screenshots-v24" style="margin-left: auto; margin-right: auto;" target="_blank" title="Terminal Map Remake Progress Screenshots V2 - Indie DB"><img alt="Terminal Map Remake Progress Screenshots V2" src="https://media.indiedb.com/cache/images/engines/1/1/427/thumb_620x2000/T2.jpg" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;"><b>Dark Spots Removed Pic-3</b></td></tr></tbody></table><div><br /></div><div><br /></div><div> In Autodesk Maya 2015, click on Normals at the top and select Unlock Normals. This helped to remove the dark spots on the models and made the textures far clearer and improved their visibility. To verify that the normals are unlocked:<br /><br />1.) Go to Display<br />2.) Select Polygons <br />3.) Then select Vertex Normals. <br /><br />Normals should show a green line when unlocked and yellow when locked. Leave them unlocked. You can see the results of the removed dark spots in the video below. Some of the textures still pop-in and out so they will have to be resized. </div><div><br /></div><div><br /></div>
<div style="text-align: center;"><iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen="" frameborder="0" height="351" src="https://www.youtube.com/embed/oublAayfUVo" title="YouTube video player" width="624"></iframe></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: left;"> Please note that the gameplay footage showcased in the videos above are very early stages of development and should not be considered representative of the final product. We want to emphasize that significant progress and improvements are yet to come, as we continue to refine and polish the game. During this early phase, our main focus was on establishing the core mechanics and functionality of the game. The level design, character animations, textures, and overall visual quality are all subject to change and refinement in the upcoming stages of development. We understand that the current gameplay footage may lack certain features, exhibit placeholder assets, or have performance issues that will be addressed in due course. <br /><br /> It is crucial to keep in mind that this is just a glimpse into our development process and a work in progress. We remain committed to delivering a high-quality and enjoyable gaming experience. As we progress further, we will be implementing additional features, enhancing the visuals, optimizing performance, and addressing any issues that may arise along the way. We appreciate your support and understanding as we continue to work tirelessly to bring you the best possible version of our game. Stay tuned for future updates and be assured that the final product will be a significant improvement over this early footage.</div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div>Jordon McClainhttp://www.blogger.com/profile/18342097908172252205noreply@blogger.com0tag:blogger.com,1999:blog-3257117917071262914.post-17441838057392865192023-03-23T21:08:00.014-07:002023-04-14T23:08:46.122-07:0087.) Cyclone Game Engine Character Physics Controller Part 2<div style="text-align: center;"><iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen="" frameborder="0" height="351" src="https://www.youtube.com/embed/OnWvSCUW0wo" title="YouTube video player" width="624"></iframe></div><div style="text-align: center;"><br /></div><div style="text-align: left;"> Because of limited time, the design and creation of 3D models was placed on hold to focus on getting the physics collision working with low-poly models properly. I went back and utilized the Stage 1 scene from the Robot Game Starter Kit for testing purposes. It not only provided me with rapid results and made me very happy, but gave me room to further expand and modify the scene in the future for improving the graphics. I plan to add particle effects, shaders and more models.</div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div>
<div style="text-align: center;"><a href="https://www.indiedb.com/engines/cyclone-engine/images/cyclone-game-engine-character-controller-pics-part-2" target="_blank" title="Cyclone Game Engine Character Controller Pics Part-2 - Indie DB"><img alt="Cyclone Game Engine Character Controller Pics Part-2" src="https://media.indiedb.com/cache/images/engines/1/1/427/thumb_620x2000/Cyclone_Game_Engine_p1.jpg" /></a></div><div style="text-align: center;"><br /></div><div style="text-align: left;"> I used JigLibX as the physics engine which is one of the favored open-source physics engines for physics and collision detection. Using JigLibX was a one of the best decisions about this project because it allowed me to focus more on gameplay, instead of spending time on creating my own physics library. JigLibX is a physics engine written in C# using Microsoft's XNA framework. It is based off the physics engine JigLib and I am currently porting it to MonoGame and further expanding it. Having a collision system and a rigid body physics engine makes JigLibX one of the favored free open-source physics engines designed for use with XNA.</div><div><br /></div><div><br /></div><div><br /><div style="text-align: center;">
<a href="https://www.indiedb.com/engines/cyclone-engine/images/cyclone-game-engine-character-controller-pics-part-21" target="_blank" title="Cyclone Game Engine Character Controller Pics Part-2 - Indie DB"><img alt="Cyclone Game Engine Character Controller Pics Part-2" src="https://media.indiedb.com/cache/images/engines/1/1/427/thumb_620x2000/Cyclone_Game_Engine_P2.jpg" /></a></div><div><br /></div><div> With my<b><a href="https://jordonmd.blogspot.com/2023/02/86-ai-obstacle-avoidance-star.html" target="_blank"> Ai obstacle-avoidance and steering behaviors</a></b> sample working recently, I might expand this map to create an arcade style wave based survival game prototype starting out. The player will fight off hordes of various enemies and creatures to rack up a large kill count and points. I don't want to get too far ahead of myself but I think this prototype will hold a lot of potential. </div><div><br /></div><div><br /></div><div style="text-align: center;">
<a href="https://www.indiedb.com/engines/cyclone-engine/images/cyclone-game-engine-character-controller-pics-part-22" target="_blank" title="Cyclone Game Engine Character Controller Pics Part-2 - Indie DB"><img alt="Cyclone Game Engine Character Controller Pics Part-2" src="https://media.indiedb.com/cache/images/engines/1/1/427/thumb_620x2000/Cyclone_Game_Engine_P3.jpg" /></a></div><div><br /></div><div> I plan on implementing <b><a href="https://jordonmd.blogspot.com/2016/05/36-xna-40-parallax-occlusion-mapping.html" target="_blank">Parallax Occlusion Mapping</a></b> to make the textures pop out and add depth to the textures so that they don't appear too flat. </div><div><br /></div><div><br /></div><div style="text-align: center;">
<a href="https://www.indiedb.com/engines/cyclone-engine/images/cyclone-game-engine-character-controller-pics-part-218" target="_blank" title="Cyclone Game Engine Character Controller Pics Part-2 - Indie DB"><img alt="Cyclone Game Engine Character Controller Pics Part-2" src="https://media.indiedb.com/cache/images/engines/1/1/427/thumb_620x2000/Cyclone_Game_Engine_P19.jpg" /></a></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;">
<a href="https://www.indiedb.com/engines/cyclone-engine/images/cyclone-game-engine-character-controller-pics-part-219" target="_blank" title="Cyclone Game Engine Character Controller Pics Part-2 - Indie DB"><img alt="Cyclone Game Engine Character Controller Pics Part-2" src="https://media.indiedb.com/cache/images/engines/1/1/427/thumb_620x2000/Cyclone_Game_Engine_P20.jpg" /></a></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;">
<a href="https://www.indiedb.com/engines/cyclone-engine/images/cyclone-game-engine-character-controller-pics-part-23" target="_blank" title="Cyclone Game Engine Character Controller Pics Part-2 - Indie DB"><img alt="Cyclone Game Engine Character Controller Pics Part-2" src="https://media.indiedb.com/cache/images/engines/1/1/427/thumb_620x2000/Cyclone_Game_Engine_P4.jpg" /></a></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;">
<a href="https://www.indiedb.com/engines/cyclone-engine/images/cyclone-game-engine-character-controller-pics-part-24" target="_blank" title="Cyclone Game Engine Character Controller Pics Part-2 - Indie DB"><img alt="Cyclone Game Engine Character Controller Pics Part-2" src="https://media.indiedb.com/cache/images/engines/1/1/427/thumb_620x2000/Cyclone_Game_Engine_P5.jpg" /></a></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;">
<a href="https://www.indiedb.com/engines/cyclone-engine/images/cyclone-game-engine-character-controller-pics-part-25" target="_blank" title="Cyclone Game Engine Character Controller Pics Part-2 - Indie DB"><img alt="Cyclone Game Engine Character Controller Pics Part-2" src="https://media.indiedb.com/cache/images/engines/1/1/427/thumb_620x2000/Cyclone_Game_Engine_P6.jpg" /></a></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;">
<a href="https://www.indiedb.com/engines/cyclone-engine/images/cyclone-game-engine-character-controller-pics-part-26" target="_blank" title="Cyclone Game Engine Character Controller Pics Part-2 - Indie DB"><img alt="Cyclone Game Engine Character Controller Pics Part-2" src="https://media.indiedb.com/cache/images/engines/1/1/427/thumb_620x2000/Cyclone_Game_Engine_P7.jpg" /></a></div><div style="text-align: center;"><br /></div><div style="text-align: left;"> I might implement <b><a href="https://jordonmd.blogspot.com/search/label/deferred%20rendering" target="_blank">Deferred Rendering</a></b> which will allow the game engine to render a huge number of dynamic lights very efficiently.</div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;">
<a href="https://www.indiedb.com/engines/cyclone-engine/images/cyclone-game-engine-character-controller-pics-part-27" target="_blank" title="Cyclone Game Engine Character Controller Pics Part-2 - Indie DB"><img alt="Cyclone Game Engine Character Controller Pics Part-2" src="https://media.indiedb.com/cache/images/engines/1/1/427/thumb_620x2000/Cyclone_Game_Engine_P8.jpg" /></a></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;">
<a href="https://www.indiedb.com/engines/cyclone-engine/images/cyclone-game-engine-character-controller-pics-part-28" target="_blank" title="Cyclone Game Engine Character Controller Pics Part-2 - Indie DB"><img alt="Cyclone Game Engine Character Controller Pics Part-2" src="https://media.indiedb.com/cache/images/engines/1/1/427/thumb_620x2000/Cyclone_Game_Engine_P9.jpg" /></a></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;">
<a href="https://www.indiedb.com/engines/cyclone-engine/images/cyclone-game-engine-character-controller-pics-part-29" target="_blank" title="Cyclone Game Engine Character Controller Pics Part-2 - Indie DB"><img alt="Cyclone Game Engine Character Controller Pics Part-2" src="https://media.indiedb.com/cache/images/engines/1/1/427/thumb_620x2000/Cyclone_Game_Engine_P10.jpg" /></a></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;">
<a href="https://www.indiedb.com/engines/cyclone-engine/images/cyclone-game-engine-character-controller-pics-part-210" target="_blank" title="Cyclone Game Engine Character Controller Pics Part-2 - Indie DB"><img alt="Cyclone Game Engine Character Controller Pics Part-2" src="https://media.indiedb.com/cache/images/engines/1/1/427/thumb_620x2000/Cyclone_Game_Engine_P11.jpg" /></a></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;">
<a href="https://www.indiedb.com/engines/cyclone-engine/images/cyclone-game-engine-character-controller-pics-part-211" target="_blank" title="Cyclone Game Engine Character Controller Pics Part-2 - Indie DB"><img alt="Cyclone Game Engine Character Controller Pics Part-2" src="https://media.indiedb.com/cache/images/engines/1/1/427/thumb_620x2000/Cyclone_Game_Engine_P12.jpg" /></a></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;">
<a href="https://www.indiedb.com/engines/cyclone-engine/images/cyclone-game-engine-character-controller-pics-part-212" target="_blank" title="Cyclone Game Engine Character Controller Pics Part-2 - Indie DB"><img alt="Cyclone Game Engine Character Controller Pics Part-2" src="https://media.indiedb.com/cache/images/engines/1/1/427/thumb_620x2000/Cyclone_Game_Engine_P13.jpg" /></a></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;">
<a href="https://www.indiedb.com/engines/cyclone-engine/images/cyclone-game-engine-character-controller-pics-part-213" target="_blank" title="Cyclone Game Engine Character Controller Pics Part-2 - Indie DB"><img alt="Cyclone Game Engine Character Controller Pics Part-2" src="https://media.indiedb.com/cache/images/engines/1/1/427/thumb_620x2000/Cyclone_Game_Engine_P14.jpg" /></a></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;">
<a href="https://www.indiedb.com/engines/cyclone-engine/images/cyclone-game-engine-character-controller-pics-part-214" target="_blank" title="Cyclone Game Engine Character Controller Pics Part-2 - Indie DB"><img alt="Cyclone Game Engine Character Controller Pics Part-2" src="https://media.indiedb.com/cache/images/engines/1/1/427/thumb_620x2000/Cyclone_Game_Engine_P15.jpg" /></a></div><div style="text-align: center;"><br /></div><div style="text-align: left;"> I plan to add a <b><a href="https://jordonmd.blogspot.com/search/label/reflection" target="_blank">real-time reflection shader</a> </b>to the car's vehicle body. </div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;">
<a href="https://www.indiedb.com/engines/cyclone-engine/images/cyclone-game-engine-character-controller-pics-part-215" target="_blank" title="Cyclone Game Engine Character Controller Pics Part-2 - Indie DB"><img alt="Cyclone Game Engine Character Controller Pics Part-2" src="https://media.indiedb.com/cache/images/engines/1/1/427/thumb_620x2000/Cyclone_Game_Engine_P16.jpg" /></a></div><div style="text-align: center;"><br /></div><div style="text-align: left;"> Each game object is represented in the physics engine by a simplified mesh called a collision skin. The collision skins are often rough estimations of the geometry of the game object in order to make simulation faster. The chassis if this car object for example is actually composed of two boxes, one large for the bottom of the model and a smaller box for the top. Rigid body physics is the part of physics that deals with the motion of rigid bodies. Rigid body simulations are fast and easy to calculate relative to other methods of simulating physics. </div><div style="text-align: left;"><br /></div><div style="text-align: left;"> This makes it very useful in game development where performance plays an important role when trying to create a realistic playing experience. Rigid body physics can simulate movement and rotation in three dimensions and allows a body to have properties like mass, friction, torque, velocity etc. In a rigid body physics simulation, all objects are non-deformable. This means that an object can never be squeezed or bent regardless of what forces are applied to them.</div><div style="text-align: left;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;">
<a href="https://www.indiedb.com/engines/cyclone-engine/images/cyclone-game-engine-character-controller-pics-part-216" target="_blank" title="Cyclone Game Engine Character Controller Pics Part-2 - Indie DB"><img alt="Cyclone Game Engine Character Controller Pics Part-2" src="https://media.indiedb.com/cache/images/engines/1/1/427/thumb_620x2000/Cyclone_Game_Engine_P17.jpg" /></a></div><div style="text-align: center;"><br /></div><div style="text-align: left;"> The grass area will be separated into its own models and I will add <b><a href="https://jordonmd.blogspot.com/2016/09/40-plants-vegetation.html" target="_blank">plants and vegetation</a></b> to it. </div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;">
<a href="https://www.indiedb.com/engines/cyclone-engine/images/cyclone-game-engine-character-controller-pics-part-217" target="_blank" title="Cyclone Game Engine Character Controller Pics Part-2 - Indie DB"><img alt="Cyclone Game Engine Character Controller Pics Part-2" src="https://media.indiedb.com/cache/images/engines/1/1/427/thumb_620x2000/Cyclone_Game_Engine_P18.jpg" /></a></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;">
<a href="https://www.indiedb.com/engines/cyclone-engine/images/cyclone-game-engine-character-controller-pics-part-220" target="_blank" title="Cyclone Game Engine Character Controller Pics Part-2 - Indie DB"><img alt="Cyclone Game Engine Character Controller Pics Part-2" src="https://media.indiedb.com/cache/images/engines/1/1/427/thumb_620x2000/Cyclone_Game_Engine_P21.jpg" /></a></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;">
<a href="https://www.indiedb.com/engines/cyclone-engine/images/cyclone-game-engine-character-controller-pics-part-221" target="_blank" title="Cyclone Game Engine Character Controller Pics Part-2 - Indie DB"><img alt="Cyclone Game Engine Character Controller Pics Part-2" src="https://media.indiedb.com/cache/images/engines/1/1/427/thumb_620x2000/Cyclone_Game_Engine_P22.jpg" /></a></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;">
<a href="https://www.indiedb.com/engines/cyclone-engine/images/cyclone-game-engine-character-controller-pics-part-222" target="_blank" title="Cyclone Game Engine Character Controller Pics Part-2 - Indie DB"><img alt="Cyclone Game Engine Character Controller Pics Part-2" src="https://media.indiedb.com/cache/images/engines/1/1/427/thumb_620x2000/Cyclone_Game_Engine_P23.jpg" /></a></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;">
<a href="https://www.indiedb.com/engines/cyclone-engine/images/cyclone-game-engine-character-controller-pics-part-223" target="_blank" title="Cyclone Game Engine Character Controller Pics Part-2 - Indie DB"><img alt="Cyclone Game Engine Character Controller Pics Part-2" src="https://media.indiedb.com/cache/images/engines/1/1/427/thumb_620x2000/Cyclone_Game_Engine_P24.jpg" /></a></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;">
<a href="https://www.indiedb.com/engines/cyclone-engine/images/cyclone-game-engine-character-controller-pics-part-224" target="_blank" title="Cyclone Game Engine Character Controller Pics Part-2 - Indie DB"><img alt="Cyclone Game Engine Character Controller Pics Part-2" src="https://media.indiedb.com/cache/images/engines/1/1/427/thumb_620x2000/Cyclone_Game_Engine_P25.jpg" /></a></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;">
<a href="https://www.indiedb.com/engines/cyclone-engine/images/lens-flare-updated-effect" target="_blank" title="Lens Flare Updated Effect - Indie DB"><img alt="Lens Flare Updated Effect" src="https://media.indiedb.com/cache/images/engines/1/1/427/thumb_620x2000/LensFlare_1.jpg" /></a></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;">
<a href="https://www.indiedb.com/engines/cyclone-engine/images/lens-flare-updated-effect1" target="_blank" title="Lens Flare Updated Effect - Indie DB"><img alt="Lens Flare Updated Effect" src="https://media.indiedb.com/cache/images/engines/1/1/427/thumb_620x2000/LensFlare_2.jpg" /></a></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;">
<a href="https://www.indiedb.com/engines/cyclone-engine/images/lens-flare-updated-effect2" target="_blank" title="Lens Flare Updated Effect - Indie DB"><img alt="Lens Flare Updated Effect" src="https://media.indiedb.com/cache/images/engines/1/1/427/thumb_620x2000/LensFlare_3.jpg" /></a></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;">
<a href="https://www.indiedb.com/engines/cyclone-engine/images/cyclone-game-engine-character-controller-pics-part-225" target="_blank" title="Cyclone Game Engine Character Controller Pics Part-2 - Indie DB"><img alt="Cyclone Game Engine Character Controller Pics Part-2" src="https://media.indiedb.com/cache/images/engines/1/1/427/thumb_620x2000/Cyclone_Game_Engine_P26.jpg" /></a></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;">
<a href="https://www.indiedb.com/engines/cyclone-engine/images/cyclone-game-engine-character-controller-pics-part-226" target="_blank" title="Cyclone Game Engine Character Controller Pics Part-2 - Indie DB"><img alt="Cyclone Game Engine Character Controller Pics Part-2" src="https://media.indiedb.com/cache/images/engines/1/1/427/thumb_620x2000/Cyclone_Game_Engine_P27.jpg" /></a></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;">
<a href="https://www.indiedb.com/engines/cyclone-engine/images/cyclone-game-engine-character-controller-pics-part-227" target="_blank" title="Cyclone Game Engine Character Controller Pics Part-2 - Indie DB"><img alt="Cyclone Game Engine Character Controller Pics Part-2" src="https://media.indiedb.com/cache/images/engines/1/1/427/thumb_620x2000/Cyclone_Game_Engine_P28.jpg" /></a></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;">
<a href="https://www.indiedb.com/engines/cyclone-engine/images/cyclone-game-engine-character-controller-pics-part-228" target="_blank" title="Cyclone Game Engine Character Controller Pics Part-2 - Indie DB"><img alt="Cyclone Game Engine Character Controller Pics Part-2" src="https://media.indiedb.com/cache/images/engines/1/1/427/thumb_620x2000/Cyclone_Game_Engine_P29.jpg" /></a>
</div></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: left;"><b>More Robot Mechs Coming!</b></div><div><br /></div><div style="text-align: center;"><iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen="" frameborder="0" height="351" src="https://www.youtube.com/embed/g4pzF-TJukU" title="YouTube video player" width="624"></iframe></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div>Jordon McClainhttp://www.blogger.com/profile/18342097908172252205noreply@blogger.com0tag:blogger.com,1999:blog-3257117917071262914.post-85751454463737036662023-02-15T06:08:00.004-08:002023-02-15T13:56:55.272-08:0086.) Ai Obstacle Avoidance & A-Star Pathfinding Behaviors<div style="text-align: center;"><iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen="" frameborder="0" height="351" src="https://www.youtube.com/embed/iag52WCBi1A" title="YouTube video player" width="624"></iframe></div><div style="text-align: center;"><br /></div><p> Originally created by David Ang, this demo showcases a tower defense game where entities (spiders and marines) try to reach a destination (blue fiery portal) while avoiding obstacles using either steering behavior (spiders) or A* (marines) pathfinding. Tanks have been added as towers that rotate to face the furthest entity within its range. Particle effects are utilized to show starting points and destination points. This demo outlines the code for the entities avoiding obstacles with a bounding sphere and finding a path using A*. This 3D sample also implements particle systems defined by XML files loaded with the Content Pipeline. David's <b><a href="https://programmingmind.net/demo/avoiding-steering-behaviour-and-pathfinding-using-a-star" target="_blank">original demo</a></b> was created in XNA 3.1. I have successfully updated the source code to XNA 4.0 and made additional implementations. The sample originally utilized the Skinned Model Library but I've replaced it with an updated version of the XNAnimation Library. Doing so allowed me to resolve animation take issues within the spider model and support multiple animation clips within the same .fbx model file. </p><p><br /></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjTELMCkvl-AnXF_vLyoZcQGiPkY4sk8-JYPEv7bTe8Y3FXHptbgAxzMleBHzF-tRLoGM7aAZwfKeIODBGL23_0cxOCh1-8f7gSIdukM6GeYDPRTFi6FH4uXkBud1GOKtYftwkQ9reeiXm_4c_6IrIcyJeRp-Owg01lHqkavVeWve7_PpT3mMeg-4cS/s1271/bandicam%202023-02-12%2006-27-27-071.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="702" data-original-width="1271" height="348" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjTELMCkvl-AnXF_vLyoZcQGiPkY4sk8-JYPEv7bTe8Y3FXHptbgAxzMleBHzF-tRLoGM7aAZwfKeIODBGL23_0cxOCh1-8f7gSIdukM6GeYDPRTFi6FH4uXkBud1GOKtYftwkQ9reeiXm_4c_6IrIcyJeRp-Owg01lHqkavVeWve7_PpT3mMeg-4cS/w629-h348/bandicam%202023-02-12%2006-27-27-071.jpg" width="629" /></a></div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: left;"> I look forward to expanding this inside the Cyclone Game Engine. Soon I plan to add additional particle effects and possibly a level editor. I have provided the source code to this demo below. </div><div class="separator" style="clear: both; text-align: left;"><br /></div><div class="separator" style="clear: both; text-align: left;"><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj39Q7rudSUJ9kJhIzUNEyUFuWnxgHWTgSrL4cac9Oq2Ar-8aCcffFlrwlzcLok3yiZQymJS_Xv-lgiZ1jWfk6cDIdNJef1bfvCYhsHKZUE4F0Yd6729Gl52PHkztO9wOtb1J19sBo14DgpIpRpmUkveIUKSa9z3IDbQMHMwUHBh32F7pYlsUw2SWxN/s1271/bandicam%202023-02-12%2006-27-49-882.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="702" data-original-width="1271" height="349" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj39Q7rudSUJ9kJhIzUNEyUFuWnxgHWTgSrL4cac9Oq2Ar-8aCcffFlrwlzcLok3yiZQymJS_Xv-lgiZ1jWfk6cDIdNJef1bfvCYhsHKZUE4F0Yd6729Gl52PHkztO9wOtb1J19sBo14DgpIpRpmUkveIUKSa9z3IDbQMHMwUHBh32F7pYlsUw2SWxN/w633-h349/bandicam%202023-02-12%2006-27-49-882.jpg" width="633" /></a></div><br /><div class="separator" style="clear: both; text-align: left;"><br /></div><br /><p><br /></p>
<iframe frameborder="0" height="180" src="https://www.indiedb.com/engines/cyclone-engine/downloads/ai-obstacle-avoidance-a-star-pathfinding-xna-demo/widget" width="600"></iframe><br /><br />Jordon McClainhttp://www.blogger.com/profile/18342097908172252205noreply@blogger.com0tag:blogger.com,1999:blog-3257117917071262914.post-65425601403139116152023-01-18T00:36:00.001-08:002023-01-18T00:36:15.468-08:0085.) The Rise & Fall of Windows Silverlight<div class="flex flex-grow flex-col gap-3"><div class="min-h-[20px] flex flex-col items-start gap-4 whitespace-pre-wrap"><div class="markdown prose w-full break-words dark:prose-invert light"><p> Windows Silverlight was a development platform created by Microsoft that was designed to help developers create interactive web applications. It was first released in 2007 and was intended to be a competitor to Adobe Flash. Silverlight was built on top of the .NET Framework, which made it easy for developers to create web applications using familiar programming languages like C# and Visual Basic.</p><p> The rise of Silverlight can be attributed to its ability to provide a rich, interactive user experience on the web. It was used to create a wide range of applications, including video players, games, and interactive data visualization. Silverlight's support for multimedia and its ability to run in a web browser made it a popular choice among developers.</p><p> However, despite its initial success, Silverlight's popularity began to decline in the late 2000s. One of the main reasons for this was the rise of HTML5, which is a more modern web development platform that is supported by all major web browsers. HTML5 provides many of the same features that Silverlight does, such as support for multimedia and interactive content, but it does so in a way that is more widely supported and does not require a plugin to be installed.</p><p> Another factor in Silverlight's decline was its relationship with XNA. XNA was a development platform created by Microsoft that was primarily used for creating games on the Xbox 360 and Windows platforms. XNA was built on top of the .NET Framework, just like Silverlight, and it was intended to be used in conjunction with Silverlight to create cross-platform web games. However, the XNA development platform was discontinued in 2013, which made it more difficult for developers to create games using Silverlight.</p><p> In conclusion, Windows Silverlight was a popular development platform that was used to create interactive web applications. However, the rise of HTML5 and the discontinuation of XNA were significant factors in its decline. Despite this, Silverlight's legacy can still be seen in the many web applications that were created using it, and it continues to be used in some enterprise scenarios.</p><p> </p><p> </p></div></div></div><p></p>Jordon McClainhttp://www.blogger.com/profile/18342097908172252205noreply@blogger.com0tag:blogger.com,1999:blog-3257117917071262914.post-21559236454802914142022-12-27T06:20:00.002-08:002022-12-28T04:59:35.966-08:0084.) Steel Cyclone Studios Launches 3D Assets for Sale!!<div class="sketchfab-embed-wrapper"><div style="text-align: center;"><iframe allow="autoplay; fullscreen; xr-spatial-tracking" allowfullscreen="" execution-while-not-rendered="" execution-while-out-of-viewport="" frameborder="0" height="480" mozallowfullscreen="true" src="https://sketchfab.com/models/67ba135cf64c4632b17fbc49cb771882/embed" title="Game Over Monster Truck Model V1 (Version One)" web-share="" webkitallowfullscreen="true" width="640" xr-spatial-tracking=""> </iframe></div> <p style="color: #4a4a4a; font-size: 13px; font-weight: normal; margin: 5px;"> <a href="https://sketchfab.com/3d-models/game-over-monster-truck-model-v1-version-one-67ba135cf64c4632b17fbc49cb771882?utm_medium=embed&utm_campaign=share-popup&utm_content=67ba135cf64c4632b17fbc49cb771882" style="color: #1caad9; font-weight: bold;" target="_blank"> Game Over Monster Truck Model V1 (Version One) </a> by <a href="https://sketchfab.com/steelcyclonestudios?utm_medium=embed&utm_campaign=share-popup&utm_content=67ba135cf64c4632b17fbc49cb771882" style="color: #1caad9; font-weight: bold;" target="_blank"> steelcyclonestudios </a> on <a href="https://sketchfab.com?utm_medium=embed&utm_campaign=share-popup&utm_content=67ba135cf64c4632b17fbc49cb771882" style="color: #1caad9; font-weight: bold;" target="_blank">Sketchfab</a></p></div>
<div><br /><div> Forget about the hassles of modeling or paying someone to create your 3D assets. Find high quality 3D models that are perfect for everyone from game developers to interior designers and more. Do you want to make progress on your projects but worried you don't have the time or the budget? Cut out all the middlemen, buy directly from Steel Cyclone Studios on Gumroad and save! Import 3D objects and scenes from their library of popular models. Work with a small set of high-quality assets that are easy to modify, assemble and reuse. Save time with pre-built content that is available in the libraries to suit your needs. Save hours of time and money with their affordable products and take your game projects to new heights with these 3D models. </div><div><br /></div><div><br />
<script src="https://gumroad.com/js/gumroad-embed.js"></script><div class="gumroad-product-embed"><a href="https://steelcyclonestudios.gumroad.com/l/gameovermonstertruck">Loading...</a></div><div class="gumroad-product-embed"><br /></div><div class="gumroad-product-embed"><div class="gumroad-product-embed"><br /></div><div class="gumroad-product-embed"></div><div><br /></div></div></div></div>Jordon McClainhttp://www.blogger.com/profile/18342097908172252205noreply@blogger.com0tag:blogger.com,1999:blog-3257117917071262914.post-12122784111984341132022-12-10T00:12:00.003-08:002023-02-28T04:03:39.118-08:0083.) Free HK17 Prototype 3D Model Giveaway!<div class="sketchfab-embed-wrapper"><div style="text-align: center;"><iframe allow="autoplay; fullscreen; xr-spatial-tracking" allowfullscreen="" execution-while-not-rendered="" execution-while-out-of-viewport="" frameborder="0" height="480" mozallowfullscreen="true" src="https://sketchfab.com/models/08ea4cf491e6439ebef81411d0b2e1a6/embed" title="HK17 Prototype" web-share="" webkitallowfullscreen="true" width="640" xr-spatial-tracking=""> </iframe></div> <p style="color: #4a4a4a; font-size: 13px; font-weight: normal; margin: 5px;"> <a href="https://sketchfab.com/3d-models/hk17-prototype-08ea4cf491e6439ebef81411d0b2e1a6?utm_medium=embed&utm_campaign=share-popup&utm_content=08ea4cf491e6439ebef81411d0b2e1a6" style="color: #1caad9; font-weight: bold;" target="_blank"> HK17 Prototype </a> by <a href="https://sketchfab.com/steelcyclonestudios?utm_medium=embed&utm_campaign=share-popup&utm_content=08ea4cf491e6439ebef81411d0b2e1a6" style="color: #1caad9; font-weight: bold;" target="_blank"> steelcyclonestudios </a> on <a href="https://sketchfab.com?utm_medium=embed&utm_campaign=share-popup&utm_content=08ea4cf491e6439ebef81411d0b2e1a6" style="color: #1caad9; font-weight: bold;" target="_blank">Sketchfab</a></p><p style="color: #4a4a4a; font-size: 13px; font-weight: normal; margin: 5px;"><br /></p><p style="margin: 5px;"><br /></p></div> The HK417 is a battle rifle modeled after Heckler & Koch. This is a free prototype model you can use for your commercial and non-commercial projects. It includes an EOTech EXPS3 holosight, Grip, Scout-Light and Suppressor. <div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiGZliQ3JMpoRSV0Eg4ER5j46RGFlBue9kYHbErfuMTZ_hFyq7MVerTjv_mggi-OQ6Xr6FweDJNvsAj09ljefMMUvc9zTdsoox0U562xcSlCbTB4-dnkbxINB-N3dGALggtTWyAPe14zDntP_P3X1X8aNvrKDzomaxs51DWGpCuyt2K5CmQnm2PNeP/s4032/Weapon.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><br /><img border="0" data-original-height="2268" data-original-width="4032" height="373" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiGZliQ3JMpoRSV0Eg4ER5j46RGFlBue9kYHbErfuMTZ_hFyq7MVerTjv_mggi-OQ6Xr6FweDJNvsAj09ljefMMUvc9zTdsoox0U562xcSlCbTB4-dnkbxINB-N3dGALggtTWyAPe14zDntP_P3X1X8aNvrKDzomaxs51DWGpCuyt2K5CmQnm2PNeP/w662-h373/Weapon.jpg" width="662" /></a></div><br /><div style="text-align: center;"><br /></div><div><div style="text-align: center;">It’s not entirely as accurate as I hoped, so I’ve made it available for free. Enjoy</div><div><br /></div><div><br /></div><div><br /></div><div><br /></div></div>Jordon McClainhttp://www.blogger.com/profile/18342097908172252205noreply@blogger.com0tag:blogger.com,1999:blog-3257117917071262914.post-6436154251651942832022-12-06T00:19:00.003-08:002022-12-06T05:02:12.481-08:0082.) Free 3D Monster Truck Model Giveaway!<div class="sketchfab-embed-wrapper" style="text-align: left;"> <div style="text-align: center;"><iframe allow="autoplay; fullscreen; xr-spatial-tracking" allowfullscreen="" execution-while-not-rendered="" execution-while-out-of-viewport="" frameborder="0" height="480" mozallowfullscreen="true" src="https://sketchfab.com/models/96d16754451d4ca3a0b4c5252452f0b5/embed" title="Free Monster Truck Model" web-share="" webkitallowfullscreen="true" width="640" xr-spatial-tracking=""> </iframe></div> <p style="color: #4a4a4a; font-size: 13px; font-weight: normal; margin: 5px;"> <a href="https://sketchfab.com/3d-models/free-monster-truck-model-96d16754451d4ca3a0b4c5252452f0b5?utm_medium=embed&utm_campaign=share-popup&utm_content=96d16754451d4ca3a0b4c5252452f0b5" style="color: #1caad9; font-weight: bold;" target="_blank"> Free Monster Truck Model </a> by <a href="https://sketchfab.com/steelcyclonestudios?utm_medium=embed&utm_campaign=share-popup&utm_content=96d16754451d4ca3a0b4c5252452f0b5" style="color: #1caad9; font-weight: bold;" target="_blank"> steelcyclonestudios </a> on <a href="https://sketchfab.com?utm_medium=embed&utm_campaign=share-popup&utm_content=96d16754451d4ca3a0b4c5252452f0b5" style="color: #1caad9; font-weight: bold;" target="_blank">Sketchfab</a></p><p style="color: #4a4a4a; font-size: 13px; font-weight: normal; margin: 5px;"> </p></div><p> Download this awesome FREE 3D Monster Truck model to use in your projects for commercial or non-commercial use!! It’s not perfect by any means, however its free and great to jump-start a vehicle in your game project. Courtesy of Steel Cyclone Studios, the file comes in .fbx. - Enjoy!</p><p><br /></p><p style="text-align: center;">
<iframe frameborder="0" height="180" src="https://www.indiedb.com/company/steel-cyclone-studios/addons/free-monster-truck/widget" width="600"></iframe></p><p></p><p><br /><br /></p>Jordon McClainhttp://www.blogger.com/profile/18342097908172252205noreply@blogger.com0tag:blogger.com,1999:blog-3257117917071262914.post-82829483990247279382022-09-21T04:23:00.003-07:002022-09-27T04:13:16.039-07:0081.) Adobe Fuse & Mixamo Fuse Character Creation!<div style="text-align: center;"><iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/3by-rteNZek" title="YouTube video player" width="560"></iframe></div><div style="text-align: center;"><br /></div><div style="text-align: left;"> Created by Mixamo, Fuse is a 3D computer graphics program that helps you to quickly and easily create 3D characters. Formerly known as Fuse Character Creator, it's a fantastic tool for video game developers, modders and enthusiasts. You can edit 3D characters with ease by choosing parts as you require and pulling and pushing them to change the appearance. </div><div style="text-align: left;"><br /></div><div style="text-align: left;"><br /></div><div style="text-align: center;">
<iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/YglJGWlWsr4" title="YouTube video player" width="560"></iframe></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;">
<iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/Y6RdegCYg8w" title="YouTube video player" width="560"></iframe></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/Ht0ekszftsA" title="YouTube video player" width="560"></iframe></div><div><br /></div><div><br /></div><div><br /></div><div style="text-align: center;">
<iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/npWY48RSAQY" title="YouTube video player" width="560"></iframe></div><div><br /></div><div><br /></div><div><br /></div><div style="text-align: center;">
<iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/3p8A7hsEnwk" title="YouTube video player" width="560"></iframe></div><div><br /></div><div><br /></div><div><br />
<div style="text-align: center;"><b>Adobe Fuse Discontinued?</b></div><div style="text-align: center;"><br /></div><div style="text-align: center;">
<iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/nTnYHKA81UM" title="YouTube video player" width="560"></iframe></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;">
<iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/fZFGnEPCzIY" title="YouTube video player" width="560"></iframe></div><div><br /></div><div> Fuse has been removed from Creative Cloud and is no longer available for download. However, I have made it available at the downloadable links provided below. Feel free to download it; it's safe. I hope people find this useful. Enjoy!!</div><div><br /></div><div><br /></div><div><b>Download Adobe Fuse!! </b><br /><ul style="text-align: left;"><li><b><a href="https://www.mediafire.com/file/xp5mdsynfbra1cm/AdobeFuseInstaller.7z/file">MediaFire</a></b></li></ul><div><br /></div></div><div><br /></div></div>Jordon McClainhttp://www.blogger.com/profile/18342097908172252205noreply@blogger.com0tag:blogger.com,1999:blog-3257117917071262914.post-48219294346751950852022-07-15T14:24:00.003-07:002022-07-15T15:20:33.720-07:0080.) 3D Game Map In Development of a Futuristic Base Level<div style="text-align: center;"><a href="https://www.indiedb.com/members/jdawgg25/images/map5" target="_blank" title="Map - Indie DB"><img alt="Map" src="https://media.indiedb.com/cache/images/members/1/668/667275/thumb_620x2000/Map.jpg" /></a></div><div style="text-align: left;"><br /></div><div style="text-align: left;"> Set atop a moon in a somewhat distant future, the map is an abandoned mining research facility once controlled by a fictional military corporation broken up into several areas. Space Mining has become a lucrative business. There are rumors and speculations that the mining facility was constructed around an alien crash site </div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div>
<div style="text-align: center;"><a href="https://www.indiedb.com/members/jdawgg25/images/map4" target="_blank" title="Map - Indie DB"><img alt="Map" src="https://media.indiedb.com/cache/images/members/1/668/667275/thumb_620x2000/Capture1.PNG" /></a></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;">
<a href="https://www.indiedb.com/members/jdawgg25/images/map3" target="_blank" title="Map - Indie DB"><img alt="Map" src="https://media.indiedb.com/cache/images/members/1/668/667275/thumb_620x2000/Capture2.PNG" /></a></div><div style="text-align: center;"><br /></div><div style="text-align: left;"> The base contains solar-powered roads. They are roads “paved” with extremely strong solar panels that are covered in glass that can withstand environmental stressors and the weight of vehicles driving over them on a consistent basis. The roads help to both store and produce electricity wherever needed. </div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;">
<a href="https://www.indiedb.com/members/jdawgg25/images/map2" target="_blank" title="Map - Indie DB"><img alt="Map" src="https://media.indiedb.com/cache/images/members/1/668/667275/thumb_620x2000/Capture3.PNG" /></a></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://www.indiedb.com/members/jdawgg25/images/map1" style="margin-left: auto; margin-right: auto;" target="_blank" title="Map - Indie DB"><img alt="Map" src="https://media.indiedb.com/cache/images/members/1/668/667275/thumb_620x2000/Capture4.PNG" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Top View</td></tr></tbody></table><div style="text-align: center;">
</div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;">
<a href="https://www.indiedb.com/members/jdawgg25/images/map" target="_blank" title="Map - Indie DB"><img alt="Map" src="https://media.indiedb.com/cache/images/members/1/668/667275/thumb_620x2000/Capture5.PNG" /></a></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div>Jordon McClainhttp://www.blogger.com/profile/18342097908172252205noreply@blogger.com0tag:blogger.com,1999:blog-3257117917071262914.post-89787725324483629632022-07-01T08:03:00.002-07:002022-07-18T04:00:59.222-07:0079.) Character Armor Customization Part 3<div style="text-align: center;"><iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/aSEmOFdbFoE" title="YouTube video player" width="560"></iframe></div><div style="text-align: center;"><br /></div><div style="text-align: left;"> I played around with armor customization for my avatar and transformed myself into a COG soldier inspired by Gears of War. This is an in-game video of of it running inside the cyclone game engine. The menu background scene has been updated as well. This was just for fun and learning purposes.</div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div>
<div style="text-align: center;"><iframe allow="autoplay; clipboard-write; encrypted-media; picture-in-picture; web-share" allowfullscreen="true" frameborder="0" height="497" scrolling="no" src="https://www.facebook.com/plugins/post.php?href=https%3A%2F%2Fwww.facebook.com%2Fphoto.php%3Ffbid%3D415275143943295%26set%3Da.347449210725889%26type%3D3&show_text=false&width=500" style="border: none; overflow: hidden;" width="500"></iframe></div><div><br /></div><div><br /></div><div><br /></div><div style="text-align: center;">
<iframe allow="autoplay; clipboard-write; encrypted-media; picture-in-picture; web-share" allowfullscreen="true" frameborder="0" height="498" scrolling="no" src="https://www.facebook.com/plugins/post.php?href=https%3A%2F%2Fwww.facebook.com%2Fphoto.php%3Ffbid%3D415275137276629%26set%3Da.347449210725889%26type%3D3&show_text=false&width=500" style="border: none; overflow: hidden;" width="500"></iframe></div><div><br /></div><div><br /></div><div><br /></div><div style="text-align: center;">
<iframe allow="autoplay; clipboard-write; encrypted-media; picture-in-picture; web-share" allowfullscreen="true" frameborder="0" height="498" scrolling="no" src="https://www.facebook.com/plugins/post.php?href=https%3A%2F%2Fwww.facebook.com%2Fphoto.php%3Ffbid%3D415275140609962%26set%3Da.347449210725889%26type%3D3&show_text=false&width=500" style="border: none; overflow: hidden;" width="500"></iframe></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div>Jordon McClainhttp://www.blogger.com/profile/18342097908172252205noreply@blogger.com0tag:blogger.com,1999:blog-3257117917071262914.post-20615540504890392652022-05-30T05:50:00.000-07:002022-05-30T05:50:17.916-07:0078.) Superstar McClain Animations Tests<div style="text-align: center;"><iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/Kyw58BLBHzE" title="YouTube video player" width="560"></iframe></div><div><br /></div><div><br /></div><div><br /></div><div style="text-align: center;">
<iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/rGGuPk4nJ0k" title="YouTube video player" width="560"></iframe></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div>Jordon McClainhttp://www.blogger.com/profile/18342097908172252205noreply@blogger.com3tag:blogger.com,1999:blog-3257117917071262914.post-27641290121198362112022-03-26T14:25:00.002-07:002022-03-26T14:25:30.663-07:0077.) 6 Awesome Games Made with MonoGame 2021<div style="text-align: center;"><iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/0S8pixXWqD0" title="YouTube video player" width="560"></iframe></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div>Jordon McClainhttp://www.blogger.com/profile/18342097908172252205noreply@blogger.com0tag:blogger.com,1999:blog-3257117917071262914.post-18992682075091557882021-09-12T08:59:00.001-07:002021-09-12T09:08:19.755-07:0076.) Agama Materials<div style="text-align: center;"><iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/63BypeuZR7s" title="YouTube video player" width="560"></iframe></div><div style="text-align: center;"><br /></div><div style="text-align: left;"> Looking for an alternative to Substance Painter? Then take a look at <b><a href="https://agamamaterials.com/" target="_blank">Agama Materials</a></b>! This 3D texturing painting application is a completely free tool for creating procedural PBR textures. Another application worth checking out is <b><a href="https://jordonmd.blogspot.com/search/label/material%20maker" target="_blank">Material Maker</a></b>. <br /><br /><br /><b>More Links</b><br /><ul style="text-align: left;"><li><b><a href="https://docs.agamamaterials.com/" target="_blank">Documentation</a></b></li><li><b><a href="https://agama.itch.io/agama-materials" target="_blank">Itch.io Page</a></b></li></ul><div><br /></div><div><br /></div><div><br /></div></div>Jordon McClainhttp://www.blogger.com/profile/18342097908172252205noreply@blogger.com1tag:blogger.com,1999:blog-3257117917071262914.post-35192444930570672682021-05-20T07:45:00.005-07:002021-05-20T07:45:38.995-07:0075.) Material Maker<div style="text-align: center;"></div><div style="text-align: center;"></div><div style="text-align: center;"></div><div style="text-align: center;"></div><div style="text-align: center;"></div><div style="text-align: center;"></div><div style="text-align: center;"><iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/-KCVyObMYt8" title="YouTube video player" width="560"></iframe> </div><div style="text-align: center;"><br /></div><div style="text-align: left;"> Material Maker is a procedural materials authoring and 3D model painting
tool, based on the Godot Engine. Materials and brushes are defined as
graphs where nodes create or transform textures, and can be exported for
the Godot, Unity and Unreal game engines.</div><div style="text-align: left;"> </div><div style="text-align: left;"> </div><div style="text-align: left;"><b> Downloads</b><br /><ul style="text-align: left;"><li><b><a href="https://github.com/RodZill4/material-maker" target="_blank">Github</a></b></li></ul></div><div style="text-align: left;"> </div><div style="text-align: left;"> </div><div style="text-align: left;"> </div><div style="text-align: left;"> </div>Jordon McClainhttp://www.blogger.com/profile/18342097908172252205noreply@blogger.com4tag:blogger.com,1999:blog-3257117917071262914.post-63193844809927305362021-05-01T17:08:00.006-07:002021-05-01T17:30:05.605-07:0074.) Quixel Mixer 2021 just released!!<div style="text-align: center;"></div><div style="text-align: center;"></div><div style="text-align: center;"></div><div style="text-align: center;"></div><div style="text-align: center;"></div><div style="text-align: center;"></div><div style="text-align: center;"></div><div style="text-align: center;"><iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/v2rVJa3RDAk" title="YouTube video player" width="560"></iframe><br /> </div><div style="text-align: left;"> Back in 2019, Epic Games acquired Quixel Mixer. They just released version 2021 and this amazing texturing tool comes with a host of features. Along with its materials, Quixel Mixer is actually free for commercial use. This is a huge game changer for freeware software to come out and actually push innovation. With UDIM support, Mixer is a potential great alternative to Substance Painter. One particular feature I would like to see integrate into Quixel Mizer is the symmetry tool that Substance Painter provides. Another feature I would like to see added to Quixel Mixer is <a href="https://docs.substance3d.com/spdoc/baking-109608997.html" target="_blank"><b>baking</b></a>. Substance Painter provides baking which allows you to transfer mesh based information into textures. This information is read by shaders or substance filters to perform advanced effects. Smart Materials and Smart Mask rely on them. One nice thing Quixel Mixer has is the <a href="https://quixel.com/megascans" target="_blank"><b>megascan library</b></a> and the ability to
customize megascans objects. Its decal system is superior and more
intuitive than Substance Painter in my own opinion. Quixel Mixer also provides access to a lot of quality 3D
content.<br /><br /><br /></div>
<div style="text-align: center;"></div><div style="text-align: center;"></div><div style="text-align: center;"></div><div style="text-align: center;"><iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/pLKSxRmY0NE" title="YouTube video player" width="560"></iframe><br /><br /></div><div style="text-align: left;"> </div><div style="text-align: left;">Download Quixel Mixer 2021 here: <a href="https://quixel.com/products/mixer" target="_blank"><b>https://quixel.com/products/mixer</b></a></div><div style="text-align: left;"><b> </b></div><div style="text-align: left;"><b> </b><br /></div>Jordon McClainhttp://www.blogger.com/profile/18342097908172252205noreply@blogger.com0tag:blogger.com,1999:blog-3257117917071262914.post-4081409470021937402021-01-14T15:20:00.006-08:002021-03-05T00:04:15.265-08:0073.) 3D Buzz Content All Released for FREE<div style="text-align: center;"><iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/ZF0XX0La4JM" width="560"></iframe></div><div style="text-align: center;"><br /></div><p> Since 2001, 3D Buzz has created hundreds of courses on a plethora of topics. 3D Buzz was a company dedicated to providing the world with quality technical education over 3D animation, programming, game design, and much more. They were always pushing the envelope in the development of informative lessons with an engaging and personable format. I have fond memories of discovering 3D Buzz as a young kid interested in games and computer graphics. I had a monthly subscription to 3D Buzz and to my discovery, was surprised they had closed their doors and officially shutdown early 2020. Sadly, this is due to the death from cancer of one of the principal partners in 3D Buzz, Jason Busby. RIP Jason. As a parting gift however, they have made all of their courses (art, programming, MMO, Unity, Unreal, etc. ) available for free. Note that some courses date back a couple of years and that certain technologies may have advanced since then. Still, everything is free and a lot is still useful for new and beginning game developers and designers. The video tutorials are in mp4 format so all video players should play these without any issues. There is 225GB's worth of content!<br /><br /></p><p> <b><span style="color: #93c47d;">3D Buzz Archive</span></b>: <b><a href="https://archive.org/download/buzz3darchivefixed" target="_blank">https://archive.org/download/buzz3darchivefixed</a> </b></p><p><br /><br /><br /></p>Jordon McClainhttp://www.blogger.com/profile/18342097908172252205noreply@blogger.com0tag:blogger.com,1999:blog-3257117917071262914.post-73448143738458656142021-01-02T00:25:00.003-08:002021-01-02T00:25:44.081-08:0072.) MonoGame 3.8 <div style="text-align: center;"><iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/Ns9saMWr8h4" width="560"></iframe></div><div style="text-align: center;"><br /></div><div style="text-align: left;"><br /></div><div style="text-align: left;"><br /></div><div style="text-align: left;"><br /></div>Jordon McClainhttp://www.blogger.com/profile/18342097908172252205noreply@blogger.com1tag:blogger.com,1999:blog-3257117917071262914.post-76148597240754036302020-12-28T07:09:00.001-08:002020-12-28T07:09:46.202-08:0071.) Welcome to FNA<div style="text-align: center;"><iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/LD_ZfWYuUHE" width="560"></iframe></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div>Jordon McClainhttp://www.blogger.com/profile/18342097908172252205noreply@blogger.com1tag:blogger.com,1999:blog-3257117917071262914.post-4699865717952555362020-12-05T02:42:00.004-08:002020-12-17T19:36:49.546-08:0070.) Superstar McClain is born!!!<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiB5gG0KZkeKx5_BS0Z5TlLxMTVvspbfHu9AljpGWAeazPK-3VRY-yVi9v3be-gQiQYW49Xs90adCfWrq9M71LPAzC9wLP8HazQsUhSRADPauMOJR6LH5G4RGcqtMn8x3Opr8qci6xR2M/s1272/McClain4.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="653" data-original-width="1272" height="319" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiB5gG0KZkeKx5_BS0Z5TlLxMTVvspbfHu9AljpGWAeazPK-3VRY-yVi9v3be-gQiQYW49Xs90adCfWrq9M71LPAzC9wLP8HazQsUhSRADPauMOJR6LH5G4RGcqtMn8x3Opr8qci6xR2M/w622-h319/McClain4.jpg" width="622" /></a></div><p> With the help of <b><a href="https://facegen.com/" target="_blank">FaceGen</a></b>, I was able to quickly 3D model my head from photographs and transform myself into a game character. FaceGen is a 3D modeling middle-ware produced by Singular Inversions. It has been used for player character creation in Tiger Woods PGA Tour (photo game face), The Elder Scrolls IV: Oblivion and the Football Manager series. FaceGen exports to the native formats of most popular 3D packages. The models are a bit heavy on geometry, but upon import into your favorite 3D package, detail is easily reduced. I was impressed by how accurate the results were. <br /><br /></p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYgxPg5Uh4T0-crIPRxEE2N2UWK7xae9vNb5ch_UvdT_rcVaxlTpUDoIGIPjYk6JhL9p_RMSoIa3K5gjNJtT8IesPXyP8DcbV52nkgzArBGD3UbUpPNQoFnnPzmNLHTMDabFBFLBJnbRI/s640/Me.gif" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="273" data-original-width="640" height="269" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYgxPg5Uh4T0-crIPRxEE2N2UWK7xae9vNb5ch_UvdT_rcVaxlTpUDoIGIPjYk6JhL9p_RMSoIa3K5gjNJtT8IesPXyP8DcbV52nkgzArBGD3UbUpPNQoFnnPzmNLHTMDabFBFLBJnbRI/w631-h269/Me.gif" width="631" /></a></div><br /><div style="text-align: center;"><br /></div><div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUCaFlJmGNKsxBLz0fd_A8Y0usDbvNUx6eUBowZxSyh789Je3HTYf-udsrpUNUxolpfrTchgDBnHZops6HzpRYxgugM987zM_jANmJ6l2JS0QKhwWQ8GTunqut1ew7Xits1Vs8nCZKyoQ/s640/Me+Gif.gif" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="267" data-original-width="640" height="263" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUCaFlJmGNKsxBLz0fd_A8Y0usDbvNUx6eUBowZxSyh789Je3HTYf-udsrpUNUxolpfrTchgDBnHZops6HzpRYxgugM987zM_jANmJ6l2JS0QKhwWQ8GTunqut1ew7Xits1Vs8nCZKyoQ/w628-h263/Me+Gif.gif" width="628" /></a></div><div style="text-align: center;"><br /></div><p style="text-align: center;"><br /></p><div style="text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1gUlr7zmlJaGuZOdoHhcc-kApt-y1fKtE7L67_kpJnDktaThhQMtuO3KIBvpOdxmMI8_wpx8UthMl-r0R6RRO4h-hZK5SdAwYqlifFZS_6Y7K1zuK3QgTqFBsucEmgIQR91zCwkMTLBo/s1272/McClain3.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="653" data-original-width="1272" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1gUlr7zmlJaGuZOdoHhcc-kApt-y1fKtE7L67_kpJnDktaThhQMtuO3KIBvpOdxmMI8_wpx8UthMl-r0R6RRO4h-hZK5SdAwYqlifFZS_6Y7K1zuK3QgTqFBsucEmgIQR91zCwkMTLBo/w625-h320/McClain3.jpg" width="625" /></a></div><p style="text-align: center;"><br /></p><div style="text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj5elP893ejavTKFDpYA-eyCddijNrrftggypEh_ePMiKv6m3KU4c8rvSDEB_WHo1OP579Iu0D2SSzESglTZr3dXG9I6lt6-CZMrVKwmjAaNLYe_dS9oLm8l0-6QOZOwfF5yZWo8xc5aeU/s1272/McClain1.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="653" data-original-width="1272" height="322" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj5elP893ejavTKFDpYA-eyCddijNrrftggypEh_ePMiKv6m3KU4c8rvSDEB_WHo1OP579Iu0D2SSzESglTZr3dXG9I6lt6-CZMrVKwmjAaNLYe_dS9oLm8l0-6QOZOwfF5yZWo8xc5aeU/w626-h322/McClain1.jpg" width="626" /></a></div><div style="text-align: center;"><br /></div><div style="text-align: center;"><br /></div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjqE4n_3bb62yubJnBgsNP_UP9MzamNA8cz9qI9rbmO1yu_stUAa7iBnP31QzD95lfEUDwQDQaAYqZ3WAhdDONqq-mnBlHBAqPQJXHmV0T2SzC6CwPe4zoJt7RK8d73ZBzcwZWHLL-83dA/s2573/So+Beautiful.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="1222" data-original-width="2573" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjqE4n_3bb62yubJnBgsNP_UP9MzamNA8cz9qI9rbmO1yu_stUAa7iBnP31QzD95lfEUDwQDQaAYqZ3WAhdDONqq-mnBlHBAqPQJXHmV0T2SzC6CwPe4zoJt7RK8d73ZBzcwZWHLL-83dA/w632-h300/So+Beautiful.jpg" width="632" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">SO BEAUTIFUL!! LOL </td></tr></tbody></table><br /><div style="text-align: center;"><br /></div><p></p></div>
<div style="text-align: center;"><iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/GNFv2xXf-qw" width="560"></iframe></div><div style="text-align: center;"><br /></div>Jordon McClainhttp://www.blogger.com/profile/18342097908172252205noreply@blogger.com0tag:blogger.com,1999:blog-3257117917071262914.post-17900509147488024762020-12-04T05:29:00.002-08:002020-12-05T02:47:52.570-08:0069.) Character Rig & Skeleton Bone Visualizer<div style="text-align: center;"><iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/OKHrY31Lr1Q" width="560"></iframe></div><div style="text-align: center;"><br /></div><div style="text-align: left;"> After expanding the XNAnimation library to support multiple animations working from a single .fbx model file, which I discussed in a <a href="https://jordonmd.blogspot.com/2014/06/16-custom-fbx-importer-to-import.html" target="_blank"><b>previous post</b></a>, I also adopted an approach originally created by Andy Dunn (aka The Zman). In his approach, each animation is to exported into a separate FBX file, and then a custom processor is used to merge them. With the help of <a href="https://www.mixamo.com/#/" target="_blank"><b>Mixamo</b></a>, I was able to add a wide range of animations to my game characters. Mixamo offers thousands of animations to choose from and an automatic rigging service. The base character model is solely a T-pose rig with no other additional animations. The animations from Mixamo are exported in separate files and the program plays their animations and applies them to the T-pose rig, thus animating the character. This approach essentially allows me to add an infinite number of animations. </div><div style="text-align: left;"><br /></div><div style="text-align: left;"> In short, now the engine supports both multiple animations from a single .fbx model file and animations from separate .fbx files. Essentially both methods can also be applied at once. Thanks to Tom Looman, I was able to integrate the <a href="https://coreenginedev.blogspot.com/2011/03/sgmotion-rigskeleton-visualizer.html" target="_blank"><b>Rig/Skeleton Visualizer</b></a> from the sgMotion library. It visualizes the animation skeleton to debug animation and rigging issues and helps finding bone/dummy names and indices more easily. The sgMotion library also allows you to cycle through the skeleton to highlight bones and their children. The source code to the sgMotion library can be found below. Unfortunately I had to mute the song in the video above to avoid any copyright claims.<br /><br />(Source Code & Tutorial Coming Soon)<br /><br /><b><span style="color: #6aa84f;">Special Thanks</span></b><br /><div><ul style="text-align: left;"><li>Bruno Evangelista for his original work</li><li>Carlos Augusto of Floatbox Studios for the character marine</li><li>Tom Looman for the Rig/Skeleton Visualizer</li><li>Andy Dunn (aka The Zman) for the Merge Processor </li><li>cjHazard for the FBX multi-take importer</li></ul></div><div><br /></div><div>Thanks guys!</div></div><div style="text-align: left;"><br /></div><div style="text-align: left;"><br /></div><div style="text-align: left;"><br /></div><div style="text-align: left;"><b><span style="color: #6aa84f;">sgMotion Source Code:<br /><br /></span></b></div>
<iframe frameborder="0" height="180" src="https://www.indiedb.com/company/steel-cyclone-studios/downloads/sgmotion-animation-library/widget" width="560"></iframe><br /><br />Jordon McClainhttp://www.blogger.com/profile/18342097908172252205noreply@blogger.com0tag:blogger.com,1999:blog-3257117917071262914.post-14888301166955834272020-09-23T08:27:00.005-07:002022-07-13T16:10:30.048-07:0068.) Racing Game Early Prototype Build<div style="text-align: center;"><iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/D8F-rIGudTE" width="560"></iframe></div><p> This is an old very early work-in-progress video of my racing game prototype that is still in its infancy stages of development. I probably shouldn't be showing this just yet since the city is far from completion. I am still modeling and texturing the rest of the city while planning some fun gameplay. Most of the buildings are low-poly models to serve as placeholders for now. The steering was off some in this video but I'm slowly improving the car's overall handling. I realized the car kept swerving back and forth due to my game controller's left joystick being slightly broken. Below is a sneak peek of another project showing of a super car in a mid-air jump. </p><p><br /></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJ40xrXrRcRgffB2drrcJlrDA36prSVDzkEgPK9lMdMoQeup9NOI3j9a1M4p0IDDeOVqQcwLj5BBwnpQ7oBbnBeXUee7zJGhqPESNO4KSkCXdONTTJoGR4HaNouA1KPJfCfurApxc2Ja8/s2048/20191012_022053.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1152" data-original-width="2048" height="358" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJ40xrXrRcRgffB2drrcJlrDA36prSVDzkEgPK9lMdMoQeup9NOI3j9a1M4p0IDDeOVqQcwLj5BBwnpQ7oBbnBeXUee7zJGhqPESNO4KSkCXdONTTJoGR4HaNouA1KPJfCfurApxc2Ja8/w637-h358/20191012_022053.jpg" width="637" /></a></div><br /><p style="text-align: center;"><br /></p>Jordon McClainhttp://www.blogger.com/profile/18342097908172252205noreply@blogger.com3