
Free Python Course ➞ Mini-course for beginners and experienced coders. 4 cool projects in your portfolio, live chat with the speaker. Click and find out what you can learn in the course.
Learn moreCongratulations to everyone who successfully completed the previous articles and is ready to begin the Object-Oriented Programming in C# workshop. In this workshop, we will create a simple console game. During development, we will apply the OOP principles we have already mastered, and also learn new methods and techniques that will expand your knowledge and skills in C# programming. This game will be an excellent opportunity to consolidate the theory and practical application of the material studied.
- What are classes and objects?
- Features of working with objects.
- Access modifiers, encapsulation.
- Polymorphism and method overloading.
- Polymorphism.
- Inheritance and a little more polymorphism.
- Abstract classes and interfaces.
- Practical training.
What the game will be like?
This is a console game with character graphics, allowing players to move around different locations, interact with NPCs, attack enemies, open inventory and use items. Players will be able to explore the world, complete quests and develop their skills, which will make the gameplay exciting and varied. Each element of the game will contribute to creating a unique experience and immersing you in an atmosphere of adventure.
The game will be organized as follows:
- At startup, the InitGame() method is called, where game objects, items, and so on will be created.
- Afterward, the Update() method is called, which updates the game state.
Within the Update() method, you need to implement a loop that will perform certain actions. This loop is responsible for regularly updating the state of an object in a game or application. It is important that the loop takes into account all the necessary conditions and parameters to ensure the correct functioning of the logic. Performance should also be taken into account to avoid unnecessary resource consumption. Optimizing the loop and its components will improve the overall performance of the application and enhance the user experience.
- Rendering a location or inventory.
- Receiving a key pressed by the player.
- Passing the key to the controller.
- The controller, depending on the pressed key, will call methods on game objects: for example, Move() or Use().
Three static controller classes are used to manage gameplay. These classes provide efficient interaction between various game components, allowing for optimized controls and improved performance. Each class is responsible for specific functions, simplifying development and subsequent maintenance. Using static classes avoids creating unnecessary objects and reduces memory usage, which is especially important in the context of modern games with high resource demands.
- LocationController — intercepts player actions in the location.
- InventoryController — intercepts player actions in the inventory.
- GraphicsController — manages the output.
Game data, including the location dimensions and the list of objects, are stored in the static Game class. Objects will be implemented through the GameObject (base), Player, and NPC classes. Management of location and movement within the location will be assigned to the Position class. This approach ensures clear code organization and ease of working with game elements, allowing you to easily add new objects and manage their behavior in the game.
Items in our system are represented by the Item (base class), Potion (potion), and Meal (food) classes. If an item has a usable property, it implements the IUsable interface. This allows for flexibility in managing items and interacting with players. The Potion and Meal classes extend the functionality of the Item base class, allowing for unique properties and methods for different item types.
The project is small, but including all the details in one article would be too long. Therefore, this article presents only the key points. For a complete review of the project, we recommend downloading the entire source code from the GitHub repository.
Creating Game Objects
The GameObjects class will serve as the parent class for game objects, such as Player and NPC. It will contain common properties and methods that will be used by both the Player and NPCs. This will allow for more structured and organized code, simplifying the process of further development and maintenance of the game. The GameObjects class can include characteristics such as position, health, and methods for interacting with the environment. Using inheritance in this context will help avoid code duplication and increase its reusability, which is an important aspect of game development.
The Die() method is executed when an object's health reaches zero. This method removes the object from the Game.Objects collection, which helps free up memory in the game. Destructors perform a similar function, being called before an object is deleted from memory. Effective memory management is a critical aspect of game development, as it prevents memory leaks and improves overall application performance.
The NPC class will be the basis for developing the game's artificial intelligence logic, allowing for more realistic interactions in the game. The Player class will contain the methods necessary for controlling the player character. In the future, we plan to implement functionality related to using inventory items, which will add depth to the gameplay and increase interest in the game.
Created objects will be stored in a collection of the static Game class. This collection provides efficient object management, allowing them to be easily added, removed, and modified. The static Game class serves as a central element for working with game objects, providing access to them from various parts of the application. This way, developers can focus on the game logic without worrying about the complexities of object management.
The GameMode data type is an enumeration class, which simplifies the process of creating lists in code. Using enumerations allows developers to more conveniently manage different game modes, providing a structured and understandable representation of data. This is especially useful in game development, where it is necessary to clearly define different game states and modes. With GameMode, developers can minimize the likelihood of errors associated with the use of string values and improve code readability.
An alternative to enumeration classes are numbers. We can use numeric values to represent different states or categories. This allows us to simplify our code and improve its readability, especially in cases where the number of states is limited. Using numbers instead of enumeration classes can significantly improve performance and simplify the data processing logic.
This can be inconvenient, since you will constantly have to keep track of which number was specified and for what purpose.
Graphics
To display objects and locations, we will create the GraphicsController class. This class will be responsible for rendering elements on the screen, ensuring proper graphics display and managing user interaction. It will be integrated with the main application logic, allowing us to effectively manage graphical resources and update them in real time. Later, we will look at how to implement the main methods that will allow us to load textures, display images, and handle graphics-related events.
Objects are created using symbols that vary depending on the object's direction. These symbols help visualize the orientation and shape of an object, providing a clear perception of its position in space. Varying symbols based on direction allows for a more accurate depiction of the objects' characteristics and their interactions with the environment.
Now, you need to update the Program class to create the first objects and display them in the console. This will allow you to see how your objects and their methods work. Start by initializing the necessary variables and creating class instances, then print them to the console to ensure the implementation is correct. This approach will help you better understand the structure and functionality of your code, and will also simplify further development.

Controls
To ensure the movement of the player object, it is necessary to implement a control system. It is important to create an intuitive interface that allows the player to easily control the character's movement. Effective controls include handling keyboard and controller input, as well as using physics reactions to create realistic movement. Speed, direction, and animations must be considered to ensure smooth and natural movement. Optimizing controls will improve the gameplay experience and make it more engaging.
This class checks the player's keystrokes and passes the appropriate commands to other system components. For example, it interacts with the Position class, which controls the movement of objects in the game space. This approach ensures efficient control of player actions and optimizes interaction with the game world.
Explore the movement process. This will help you better understand its functionality and features. You will be able to evaluate the effectiveness of movement in various use cases. When testing, pay attention to speed and accuracy to get a full understanding of how the mechanism works.

With the change in movement mechanics, combat interactions have also been updated. The new combat system offers players a more dynamic and strategic approach to battles. Players can use a variety of tactics, adapting to the environment and the characteristics of opponents. Updates to the combat system allow for greater character control, making every fight more engaging and exciting. This integration of movement and combat creates a unique gaming experience that will appeal to both new and experienced players.

Inventory
Inventory in the data management system begins with the definition of the Item class. This class serves as the basis for creating objects representing individual inventory items. Each Item class object contains properties such as name, description, quantity, and other characteristics that help identify and manage items. Effective use of the Item class allows for the development of a flexible and scalable inventory system, which is especially important for applications that require storing and accounting for a variety of items. Furthermore, more complex structures, such as categories or subcategories of items, can be developed based on the Item class, improving data organization and accessibility.
The Potion and Meal classes have a similar structure and functionality, differing only in their text labels. Therefore, the code for only one of these classes is presented below:
The class implements the IUsable interface, which allows it to inherit certain methods and properties. Inheriting the IUsable interface ensures compatibility with other system components and simplifies interactions between them. This allows for more modular and flexible code, which is especially important for scalable applications. Using interfaces such as IUsable helps improve the structure of your code and makes it easier to maintain.
To enable the user to view items in the inventory, you need to modify the GraphicsController class by adding a new method. This method will display the contents of the inventory and improve user interaction with the game. It is important that the implementation is intuitive and efficient. Optimizing this process will improve the usability of the interface and make the game more engaging.
In the Program class, you need to supplement the switch construct with a new mode. This will expand the functionality of the program and improve its user interface. Ensure the new version correctly handles all possible scenarios to ensure stable application operation. This change will help users navigate available modes more easily and improve the overall user experience.
Control will be implemented through the InventoryController. This component is responsible for organizing and monitoring inventory, ensuring effective stock management. The InventoryController allows users to easily track product status, update inventory data, and optimize accounting processes. Using this controller helps improve inventory management efficiency and reduce the risk of loss.
The Player object is a key element in the development of games and multimedia applications. It is responsible for managing character actions, including movement, interaction with the environment, and the execution of game tasks. Importantly, the Player object can include various properties and methods that allow you to customize its behavior to suit gameplay requirements. Proper implementation of the Player object contributes to the creation of an engaging and dynamic gaming experience, which in turn positively impacts user engagement. Developing and optimizing this object requires careful programming to ensure stable operation and high application performance.
On this page, you can learn about two new keywords. These terms are important for understanding current trends and changes in our field. Using them, you can optimize your content and improve your search engine visibility. Pay attention to their use in texts to increase their relevance and attractiveness to the target audience.
- is — checks whether the specified interface is implemented in the given object;
- as — gets the implementation of the interface.


