Hello, dear friend, you can consult us at any time if you have any questions, add WeChat: daixieit

A1: Game Graphics Assignment

CPSC 427 – Video Game Programming - Winter 2024

Due: Friday, Feb 9, 2024, before 11:59 PM via Canvas.

Description:

In the assignment you will implement a simple 2D game where the user controls a flying chicken that must dodge attacking eagles while eating bugs to gain points. The goal of this assignment is to introduce you to basic graphics programming with OpenGL by extending an existing game template. To do so, you will experiment with rendering, shaders, and event-based inputs. This assignment will utilize the tinyECS framework covered in A0.

The assignment includes both required elements (80%) and a free-form component (20%) of your choice.

•   The code template zip file (A1_template.zip) for this assignment is available in Canvas.

•   A video demonstrating the required elements (A1-Solution-Video.mp4) is available in Canvas.

Deliverables:

1.  In addition to your source code, fill in the README.md file (Markdown language as used on GitHub) with your name and a list and description of your custom features.

2.  Zip all code, README.md, and the CMake.txt files as present in the template source code and exclude any executables and compiled files.   For example, exclude the “out” and “.vs” folders.

3.  Name your file: A1-.zip, for example: A1-411111111.zip.

4.  Double check that you excluded all generated files, such as /build, .vs, /out! These consume a lot of space on our server and points will be deducted if the zip file contains any of them.   For reference, your submission zip file should be similar in size to the A1_template.zip that you downloaded.

5.  Upload the zip to Canvas.

Note, do not publish your solution (OR the solutions given to you for grading) on GitHub or any other place. Neither during the course nor after; both are considered cheating.

Required Work (80%)

1. A Playable Game (40%):

You will find comments in the source files marked with TODO A1 to help guide you in the right direction. For a basic version of the game make the following changes to the provided template:

a. Game loop: The chicken is spawned at the games start in WorldSystem::restart(), and eagles are added periodically in the games loop WorldSystem::step() with random positions and constant velocity. Inspect these sections of code to understand the game’s state. It is your task to update the positions of all entities by their respective velocities in PhysicsSystem::step(). When implemented, eagles should move to the bottom of the screen while the chicken stays stationary with velocity (0, 0).

b. Escape key: Add the ability to exit the game by pressing the escape key.

c. Chicken movement: pressing the Up/Down directional keys should make the

chicken fly up and down and pressing the Left/Right directional keys should make it fly left and right; until the respective keys are released. The keyboard callback function is located in WorldSystem::on key(). Use it to keep track of the state of the keys. You can then use it to directly modify the chicken’s position or to update its velocity. The chicken’s position and velocity are stored in a Motion data structure that is retrieved with registry.motions.get(player chicken). It is the same motion data that you have modified in task (a).

d. Eating bugs: Similar to the eagle, insert bugs at random in WorldSystem::step(). A bugis instantiated with createBug() defined in world init.hpp, give them half the speed of the eagle. Once this is working, modify the code to spawn bugs and eagles at the top of the screen, outside of the player ’s view. The eagles are dangerous for the chicken, while the bugs can be eaten by the chicken in order to obtain points.

e. Rotation: Provide mouse control for rotating the chicken. Change the movement of the chicken to follow its forward direction (e.g. if the chicken is looking down right then forward should make it move down right as well). The mouse position should   rotate the chicken and the left/right keys move the chicken along the direction it is   aligned with. You can obtain the mouse position in the WorldSystem::on mouse move() in window-coordinates, relative to the top-left of the screen. You can then calculate the rotation angle with respect to the chicken’s default facing direction (positive X axis) using the atan2(y,x) function, which then can be used to update the chicken’s orientation. Orientation is stored in the Motion structure alongside position and velocity. In order to render the correctly oriented chicken you will also need to modify RenderSystem::drawTexturedMesh() and issue the transform.rotate() command in the correct order.

f. Collisions: While the basic collision code is already implemented in

PhysicsSystem::step(), you need to properly handle the interactions between entities in World System::handle collisions(). Upon collision with an eagle, modify the chicken’s motion to be upside-down and make the chicken fall downwards.

2. OpenGL and Shaders (40%)

It is most efficient to load all required resources (mesh,shader, and textures) at once in the beginning of the game, and to keep these separate from the dynamic game logic. Inspect how the lower part of components.hpp declares all the available resources. You will have to return here for adding new assets. The actual resources, such as the mesh and texture file names, are described in the render system.hpp and loaded in the initializeGlGeometryBuffers() function in render system init.cpp. Locate and inspect the mesh and texture loading functions. Note also that the meshis constructed/loaded differently: The chicken has a more complex geometry, and each vertex has its own color, while the eagle and bugs are ‘faked’ using a texture, which is applied on a quad (two triangles).

Inspect the createBug() and createEagle() functions, they are similar. Compare these to the createChicken() function. Analyze how their renderRequests tie back to the different textures and shaders.

Rendering is initiated by RenderSystem::draw(), which in turn calls drawTextured Mesh() on all the entities in the game with a RenderRequest component. Based on the resources specified in RenderRequest, different shaders are called, and different arguments are passed to the shaders. Otherwise, the OpenGL draw commands are the same for all entities.

a. Collision animations: Trigger the following animations upon chicken collisions:

i.     Eagle: If a collision with an eagle occurs the chicken’s alive state is changed.

Add code that changes its color. Study drawTexturedMesh() to understand how the color variable is simply another component and how it is passed to  the vertex shader variable fcolor. Open shader/chicken.fs.glsl to see how it’s being used to modify the final chicken color. Then modify the color variable to make the chicken red after a collision, and switchback to its original color on reset.

ii.     Bug: Whenever a chicken eats a bug, the score should be updated in the

window title and the chicken should temporarily light up. The chicken is drawn lit up in the shader/chicken.fs.glsl shader based on its state which is passed as a uniform variable from drawTexturedMesh().

Proceed in two steps:

i.     Create a new struct called LightUp in components.hpp and add an instance to the chicken entity upon chicken-bug collision. Equip LightUp with a timer. You can follow a similar implementation for the chicken’s death with the

DeathTimer struct. Remember to add the new class to the ECS registry as well as to count down all new timers.

ii.     Pass the correct state to the shader indrawTexturedMesh() based on whether it has a LightUp component and change the light color from white to yellow    inside the shader.

b.  The wind effect demonstrated in the example video is achieved using a second-pass shader. Two-pass rendering is done by first rendering the screen to an off-screen texture (see RenderSystem::draw()). Then, in the second pass a fragment shaderis used to apply additional effects to each pixel of the texture obtained from the first  pass (RenderSystem::drawToScreen()). This is achieved by rendering a fullscreen geometry in a similar fashion to how the eagles and bugs are rendered. The two-pass rendering code is provided in RenderSystem::drawToScreen(). Your job for this part is to modify the wind fragment shader shaders/wind.fs.glsl for the wind distortion and color shift. Note that you do not need to match the solution video exactly.

•    Hints for the distortion (distort): think about the translation, what if the offset value is not uniform at all pixel locations but is varying like a wave function?   What if this wave function is varying based on time? Another helpful piece of information is that the input and output values of distort are in [0, 1], so you   should set the offset values to the right scale.

•    Hints for potential seam artifacts: your distort function may output values

outside of [0, 1], leading to wrapping artifacts at the screen border. Reduce the deformation effect towards the screen boundary to ensure it stays in range.

•    Hint for the color shift (color shift): check the function fade color in the same file. You want to shift the world slightly to yellow.

3. Creative Part (20%)

The required code changes described so far will let you earn up to 80% of the grade. To earn the remaining 20% you will need to make the game more appealing by implementing one advanced feature. You may also gain bonus points when exceeding our expectations.

Marks for the advanced features will be granted only if both they and all basic features are fully implemented and functional.

Advanced feature suggestions:

-    Give the chicken momentum such that it continues moving even when no keys are pressed, while slowly slowing down due to the drag in sky. Search online for plausible models of air friction. Implement a suitable one and explain your choice in the README file.

-    Diversify the types of obstacles floating in the air. Add two new objects with new  visuals and new behaviors, such as eagles flying in randomized arcs and a vortex that pushes all chicken, bugs and eagles towards it; be creative!

-    Add multiple chickens and let the user control the chicken that is closest to the mouse cursor, forcing the player to multitask. The ECS system should ease the  addition of multiple chicken entities.

Use your imagination to make other additions than the ones listed above, however, please make sure you focus on tasks involving OpenGL, ECS, and animation knowledge.

To support both basic and advanced visualization and control features, you need to add a toggle option where the user switches between the two modes by pushing the ‘a’ and ‘b’   keys (‘a’ for advanced mode and ‘b’ for basic mode; either at startup or during the game).

Document all the features you add in the README.md file you submit with the assignment. Advice: implement and test all the required tasks first before starting the free-form part.

To get full credit you should add at least one of the advanced features above and make it fully functional and free from bugs. The grading of additional bonuses, features, and the  size of bonuses will be at the marker’s discretion. A bonus is given for solutions that go beyond the suggestions listed above. Multiple partially implemented features will not receive full credit.

Late Policy:

Late assignments will lose 20% each day late, up to a maximum of three days.

Getting Started:

a.  Download the assignment package from Canvas and unzip the source template. It should match the structure specified in the Template section of this document.

b.  View the A1-Solution-Video.mp4 video in Canvas to get a sense of what your

solution should look like once the required parts are completed.

c.  The template is built using CMake, installed as detailed in the preliminary

assignment. In the following, we will provide operating system-dependent instructions to install the additional dependencies of Assignment 1:

Windows: it should be sufficient to open the repository folder (the one containing the CMakeLists.txt) with Visual Studio (you may have to install the VS CMake extension) and pressing Build. For a manual CMake setup on Windows follow the instructions for Linux  (below), omitting the installation of external dependencies.

Linux: please install libglfw3-dev, libsdl2-dev and libsdl2-mixer-dev using your package manager, such as apt-get install . Create an empty build directory named build in the template folder (template/build). You can configure the project using the CMake GUI or the command line. For the GUI, enter the assignment template folder (which contains a CMakeLists.txt file) as Source and the build folder as Build. Then, press Configure, and if the configuration if successful, press Generate. For the command line, cd inside the build directory and run:

cmake [path_of_assignment_template] -DCMAKE_BUILD_TYPE=[Debug|Release]

Now you can build the generated project using ‘make’ from the command line at the top-  level directory or using your favorite IDE. You will require a compiler that supports C++14.

Note: running CMake and building the project will copy files and data to the build folder. Do not edit any files in the build folder, only edit files in the src and shader folders (create new  assets in the data folder).

The template provided should compile and run on Windows and Linux. Please contact the TAs if you have any challenges with installation on these platforms. If you have an Apple device you may want to work remotely on the department Linux machines (askTAs for advice on how to connect).

d.  To verify that the installation was successful, compile and start the program from

the command line by following the prior commands, or from your IDE. It should start an OpenGL window containing a rendered chicken and eagles. Make sure that your debugger works, as detailed in the previous assignment.

You are allowed to work on the assignment in any environment and OS, but we expect your code to compile and run on the lab machines (Linux).

Provided Template:

The template code provides a starting base for your work. You will find comments

throughout the files to help guide you. A list of the files is detailed below, and the directory is structured as follows:

•   The directory src contains all the header (.hpp) and source (.cpp) files used by the project.

•   The entry point is located in main.cpp while most of the logic will be implemented in the world system (world system.cpp) and physics system (physics system.cpp).

•   The data directory contains all audiofiles, meshes, textures, and shaders used in the code.

•   The external dependencies are located in the ext subdirectory, which is referenced by the project files, it contains header files and precompiled libraries for:

o gl3w: OpenGL function pointer loading (header-only)

o glfw: Cross-platform window and input

o glm: The GLM library provides vector and matrix operations as in GLSL

o SDL/SDL mixer: Playing music and sounds

o stb image: Image loading (header-only)

Transformations and Rendering:

The template uses OpenGL 3.3 with object transformation and projection matrices passed  to the shaders. The projection matrix is set to orthographic with a view frustum of 900 × 600 that matches the window resolution (in RenderSystem::draw()). In order to ease the concatenation of multiple object transformations, such as scaling and translation, we  provide the following functions (semantics resemble legacy OpenGL with glTranslate(), glRotate() etc.):

transform(): The transformation is initialized to the identity

transform.rotate(): Applies a rotation matrix to the current transform

transform.scale(): Applies a scale matrix to the current transform

transform.translate(): Applies a translation matrix to the current transform

•   The sequence of transformations is stored as a 3× 3 matrix that is then passed to the Vertex Shader and multiplied by the (orthographic) projection matrix.

Be careful about the order of transformations as they are being multiplied before being passed as uniform data to the shaders.

Provided files:

/data/

/data/audio/

chicken_dead.wav // poor chicken

chicken_eat.wav // what the chicken says

music.wav // background music sound

/data/meshes/

chicken.obj // chicken vertices and faces (.obj file)

/data/textures/

bug.png // bug sprite texture

eagle.png // eagle sprite texture

/ext/ // external libraries: gl3w, glfw, glm, sdl, stb_image

project_path.hpp // CMake-modified information file

project_path.hpp.in // CMake source file

/shaders/

chicken.fs.glsl // chicken’s fragment shader

chicken.vs.glsl // chicken’s vertex shader

coloured.fs.glsl // simple color fragment shader example

coloured.vs.glsl // simple color vertex shader example

egg.fs.glsl // egg ’s fragment shader

egg.vs.glsl // egg ’s vertex shader

textured.fs.glsl // textured item’s fragment shader

textured.vs.glsl // textured item’s vertex shader

wind.fs.glsl // wind’s fragment shader

wind.vs.glsl // wind’s vertex shader

/src/

ai_system.cpp // placeholder for future AI

ai_system.hpp // placeholder for future AI

common.cpp // helper functions

common.hpp // helper functions, structs, and macros

components.cpp // loadFromOBJFile helper function

components.hpp // Component definitions – important global enum ID’s

main.cpp // main game loop and int main()

physics_system.cpp // simple physics system

physics_system.hpp // simple physics system

render_system.cpp // RenderSystem implementation

render_system.hpp // OpenGL setup RenderSystem

render_system_init.cpp // RenderSystem (OpenGL) initialization

tiny_ecs.hpp // Registry class definition

tiny_ecs.hpp // Registry class implementation

world_init.cpp // create functions for new named Entities

world_init.hpp // constants and function prototypes

world_system.cpp // WorldSystem implementation

world_system.hpp // WorldSystem declaration

CMakeLists.txt // your project’s CMake instructions (from template)

README.md // fill in with description of your custom features