Assignment 2: Game in C#

Due Friday, September 13, before midnight

The goals for this assignment are:

  • Write a progam in C#

  • Implement a simple game based on the Game Loop and Object Update patterns

The goal of this assignment is to write a C# Game that utilizes a game loop, game time, and the object update pattern. You can design any game you like, but choose something that you can implement in a few days. Your game should also support some kind of interaction with the player. Below is an example that fullfills these requirements:

The above video uses the WASD or arrow keys to control the player (pink squiggle). The black and white squiggles are randomly created obstacles that float from right to left. Both the player and obstacles implement the Update pattern. The game loop is implemented in the main Window (given as part of your basecode).

You are given basecode for implementing a 2D game; however, you can also write a text-based game that fullfills the requirements if you prefer. The final game should be a 2-5 minute experience that another person can eaily understand and try.

You may use an existing game that you have already written, for example a homework from intro or from your own tinkering, and port it to C#. Your game should be something that you have written!
This assignment does not use Unity!

1. Requirements

  • You must define at least one class that has an Update(dt) method and implements something that must be simulated over time.

  • Your program must take some kind of player input (e.g. is must be interactive)

  • Your program must implement a game loop. If you implement a 2D game, the game loop is implemented for you in your basecode.

2. Getting Started

First sync your fork with the class repository. This can be done from Github

SyncFork

Once synced, you can then pull the changes to your local repository where you will work using Git Bash:

alinen@sutekh MINGW64 ~/cs283-f24-assignments-test (main)
$ git pull
Enter passphrase for key '/c/Users/alinen/.ssh/id_ed25519':
remote: Enumerating objects: 9, done.
remote: Counting objects: 100% (7/7), done.
remote: Compressing objects: 100% (5/5), done.
remote: Total 9 (delta 2), reused 7 (delta 2), pack-reused 2 (from 1)
Unpacking objects: 100% (9/9), 1.87 KiB | 66.00 KiB/s, done.
From github.com:alinen/cs283-f24-assignments-test
   8c3cd6b..fc5dbcc  main       -> origin/main
Updating 8c3cd6b..fc5dbcc
Fast-forward
 .gitignore        |   2 ++
 C#/HelloWorld.exe | Bin 3584 -> 0 bytes
 C#Game/Game.cs    |  42 +++++++++++++++++++++++
 C#Game/Window.cs  |  99 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 143 insertions(+)
 delete mode 100644 C#/HelloWorld.exe
 create mode 100644 C#Game/Game.cs
 create mode 100644 C#Game/Window.cs

2.1. Compiling and Running

The C# compiler can be run from Visual Studio 2022. Under File → Open → Folder, browse to the directory that contains your code (cs283-f24-assignments/C#Game).

Inside Visual Studio, build and run from the developer console like so

$ csc *.cs
$ .\Window.exe

You should see an empty window.

You can enable developer powershell in Visual Studio from the menu. Select View → Terminal
Development

3. Program Architecture

You are given basecode for this assignment. Read through the class Window.cs. This class registers callbacks on user input (mouse and keyboard), drawing, and update. This class also implements the game loop and computes delta time.

Your code should be implemented in the class Game.cs. Game.cs is integrated with the Window class.

  • Game.Setup() is called once before the game loop starts

  • Game.Update(float dt) is called once per frame with the elapsed time in seconds

  • Game.Draw(Graphics g) is called when the window is refreshed

  • Game.MouseClick(e) is called when the user clicks a mouse button. See the Game.cs for an example of how to use it.

  • Game.KeyDown(e) is called when the user clicks presses the keyboard. See the Game.cs code for an example of how to use it.

3.1. Example

This section describes how the example game was made. The game uses three classes:

  • Game.cs which creates the objects, responds to input, and manages whether the game is over or not

  • Obstacle.cs which implements moving Obstacles

  • Player.cs which implements the Player which moves based on input

The game creates an array of Obstacle and one Player. In Update, the game updates the obstacles and the player. In Draw, the game draws the obstacles and the player. Both Obstacle and Player implement the following methods

  • Reset()

  • Draw(Graphics g)

  • Update(float dt)

Thus, updating and drawing simply calls these functions on the player and every obstacle. For example, the code to update all game objects in Game.cs looks like

foreach (Obstacle obstacle in _obstacles)
{
    obstacle.Update(dt);
}
player.Update(dt);

Drawing is handled similarly. For the player, we implemented methods called MoveUp, MoveLeft, etc. When the user pressed a movement key, we call the associated method. These methods change the direction that the player moves in Update.

4. Drawing Tips

For convenience, we are using the command in System.Drawing for this assignment. This module supports drawing simple primitives (rectangles, circles, lines, etc), text, and images. Here are some examples Every draw call requires the a reference to the Graphics object that is passed to Draw.

Draw text that is centered in the middle of the screen

public void Draw(Graphics g)
{
   Font font = new Font("Arial", 46);
   SolidBrush fontBrush = new SolidBrush(Color.White);

   StringFormat format = new StringFormat();
   format.LineAlignment = StringAlignment.Center;
   format.Alignment = StringAlignment.Center;

   g.DrawString("GAME OVER!", font, fontBrush,
      (float) (Window.width * 0.5),
      (float) (Window.height * 0.5),
      format);
}

Draw a circle

public void Draw(Graphics g)
{
    Color c = Color.FromArgb(100, 250, 0, 0); // red
    Brush brush = new SolidBrush(c);
    g.FillEllipse(brush, X, Y, Size, Size);
}

Draw a rectangle that fills the window

public void Draw(Graphics g)
{
{
    Color background = ColorTranslator.FromHtml("#142F98");
    Brush brush = new SolidBrush(background);
    g.FillRectangle(brush, 1, 1, Window.width, Window.height);
}

Draw an image

Image mImg = Image.FromFile("filename.png"); // load once during initialization

...
public void Draw(Graphics g)
{
   g.DrawImage(mImg, x, y, width, height);
}

5. Ideas

Any simple game could form a good basis for this assignment, for example,

  • Frogger

  • Neko Atsumi

  • Galaga

  • Asteroids

6. What to hand in

  • Your code

  • Updated README

    • A video or GIF showing your game play

    • Instructions on how to play, e.g. the game controls

    • Instructions on how to build

Don’t forget to commit your changes and then push them to Github. Using Git Bash, run the following command inside your A02 directory.

$ cd A02
$ git add .
$ git commit -m "Finished A02"
$ git push

Run git status to check the result of the previous git command. Check the Github website to make sure that your program uploaded correctly.

Assignment rubrics

Grades are out of 4 points.

  • Game code (3 points)

  • Readme (1 point)

Please submit your code from Lab as part of your assignment

Submission rubrics

For full credit, your program must

  • compile and run

  • contain a game loop

  • contain a list of simulated game objects that implement an Update() function

  • show effort and imagination — minimally fullfilling requirements will earn you a B (3.0)

  • Some credit lost for missing features or bugs, depending on severity of error

  • -12.5% for style errors. See the class coding style here.

  • -100% for failure to checkin work to Github

  • -100% for failure to build and run on the lab Windows machines