1 CSc 165 – Computer Game Architecture and Implementation Spring 2017 - Gordon dAssignment #1: Building A Game Using Game Engine Components Due: Wednesday, Feb 15th (2½ weeks) The objective of this assignment is to learn how to use game engine components to build a simple 3D game. You are to rely on existing game engine components to supply much of the underlying functionality while implementing some of the functionality yourself. The assignment assumes you will use the Simple Adaptable Game Engine (SAGE) provided to the class. The game to be implemented is called “SpaceFarming3D”. The player uses the keyboard and gamepad (Xbox controller or equivalent) to fly around a 3D world collecting “plants” and putting them in a “truck”. A plant is “collected” (and removed from its location) when the player flys into it (i.e., when the camera collides with a plant). As plants are collected, they are moved into a “truck” (another object in your game). The game score and elapsed time is shown on a HUD (Heads-Up Display). Game Program Requirements • Your game must extend sage.app.BaseGame, and override initGame() and update(). All game logic must reside inside these methods, or in user-written classes invoked by them. • You must use sage.scene.shape objects to build some of the objects in your game. The game initialization code should instantiate several such objects of different types (the plants), randomly positioned in the world. You should also use scale() to set the objects to various sizes. • The model for the “truck” must be a new one that is defined completely by you, in a class that extends sage.scene.TriMesh. You will need to explicitly specify the vertices, colors, and triangles as needed to construct your truck (importing a model, such as from an .OBJ file, does not fulfil this requirement – you must build it by hand). You should try and build a shape that bears some rough resemblance to a container, but it is not expected to be very realistic. • Your game must support input actions handled by Action classes. That is, you must write classes that implement sage.input.action.IAction, and your game must then utilize InputManager.associateAction() to link device components with your Action classes. • At least the following key mappings must be provided (you can can add more if you like): A/D/W/S: move camera left/right/forward/backward. Note that all camera motion is relative to the camera’s UVN axes; for example “W” moves in the direction of the camera’s N axis. Left-arrow / Right-arrow: rotate the camera (positive or negative) around its V axis (“yaw”). Up-arrow / Down-arrow: rotate the camera (positive or negative) around its U axis (“pitch”). Q/E: rotate the camera around its N axis (“roll”). ESCAPE: quit the game. • At least the following controller mappings must be provided (you can add more if you like): X-axis: move camera left and right in the same manner as the A and S keys. Y-axis: move camera forward and backward in the same manner as the W and D keys. RX-axis: yaw camera around its V axis, the same as the Left/Right arrow keys. RY-axis: pitch camera around its U axis, the same as the Up/Down arrow keys. 2 • The game must display world axes showing where the world origin is located. The X axis should be red, the Y axis is green, and the Z axis is blue. You may add an input command to toggle the axes off/on, but this is not required (if you do, the axes must initially be visible). • The game must include at least two HUD elements: current “score”, and elapsed time in seconds. Each HUD element must be implemented in a class that extends sage.scene.HUDObject. You may use sage.scene.HUDString (which extends HUDObject) to do this. You can decide on a scoring method - a simple example is to simply count the number of plants collected. • One of the objects placed in the game is the “Truck”. The Truck can be of any shape, but it must look clearly different than the plants. Whenever you collect a plant, the truck should temporarily change its appearance, such as by temporarily getting bigger or turning on a light. To trigger this happening, you will need to use SAGE’s event handling system. That means (1) creating an event class that extends AbstractGameEvent, (2) associating your event type with an IEventListener – such as the Truck, (3) detecting collisions between the camera and plants, (4) triggering an event when a collision is detected, and (5) handling the collision in the listener by changing its appearance. The truck should be placed near the origin. • When a plant is collected, it is moved inside the truck. You can line them up side-by-side, or cluster them in a bunch, but they shouldn’t all be in the exact same position. It must be possible to view the plants inside the truck from some vantage point, such as by having the top of the truck be “open”, or by looking through a window. • The game must set the window title. BaseGame provides a simple way of accessing this. Coding Style Requirements • Your code should be organized using two Java packages. As the semester progresses, you will be developing two sets of code: code for different games, and game engine routines which will replace corresponding SAGE routines. Therefore you will need at least two packages: one named a1 which houses the game you develop, and one named myGameEngine which houses game engine components which you develop to replace SAGE routines. Classes which are part of the SpaceFarming3D game itself would go in package a1, while classes which are part of your game engine (for example, classes which implement camera controller code, such as MoveForwardAction) would go in package myGameEngine. Your code should follow the Java convention that package names always start with a lower-case letter. • Your program must run correctly when invoked from a command prompt using the command java a1.Starter. This means your Starter class must be contained in the “a1” package and that it must contain the required public static void main(String [] args). The Starter code simply invokes your game’s start() method. Additional Notes • This assignment requires you to develop input actions, some of which are camera control actions. SAGE has a variety of IAction implementations for camera controls (you can find them in sage.input.action). You may find it useful to use the SAGE version to test your program -- but you must submit the completed program using YOUR implementations, not those in SAGE. 3 • “Plants” are “farmed” by running into them with the camera. This means you must do collision detection between the camera’s world location and the bounding volumes of the plants’ shapes. SAGE provides a BoundingVolume for most of its shapes. • You may use SAGE’s InputManager class; you do not have to write your own input manager. • If you do not have a controller that implements the X, Y, RX, and RY axes you may check one out from the instructor for testing purposes. • The Input Manager provided by BaseGame polls the underlying JInput event queues once each time through the game loop. Depending on your machine, the elapsed time parameter passed to the performAction() method of IAction objects will probably range from 1 to 10 milliseconds, The default SAGE IAction objects for camera manipulation (which you won’t use in this project, because you are building your own camera manipulation action objects) multiply this time value by the action speed (specified when the IAction is constructed) in order to determine the distance that camera moved. Your code should take a similar approach. • Rather than use a separate Timer to keep track of elapsed time in the HUD, you may use the elapsed time parameter that BaseGame passes to your update() method (it’s value is in msec). • You will find several helpful classes in the graphicslib3D library (that comes with SAGE): Point3D (a 3D point), Vector3D (a 3D vector) and Matrix3D (a 4x4 transformation matrix). Every SAGE shape (sage.scene.SceneNode) contains a set of three Matrix3D objects which specify the current translation, rotation and scaling transformations applied to the object. These transforms can be obtained or modified by using the appropriate getter/setter methods provided in SAGE. They are referred to as local transforms; for example you can get the translation of an object calling getLocalTranslation(). Note there are also “world” transforms in SAGE shapes; your program should not mess with these (we’ll see later what they are for). • VERY IMPORTANT Make sure that your program works on at least one workstation in the RVR-5029 lab. Don’t wait until the last minute to test this!!! I have no way of grading your homework if it doesn’t run on at least one of the lab machines! Deliverables This is an individual assignment. Submit to SacCT a single ZIP file containing: 1. your Java source code (.java) files, 2. the compiled (.class) files for each of your Java source files, 3. a batch (.bat) file that successfully runs your submission if unzipped as-is onto a lab machine, 4. a short “Player’s Guide” document (approximately 2 pages, preferably PDF), including: • your name, • a screenshot (.jpg) file showing a typical scene from your game, • how to compile and run your program from a command window, • how your game works, what the player input commands do, and the scoring, • where in your game you satisfied each the specific requirements, • any of the requirements that you weren’t able to get working, • the type of gamepad your game was tested with, and • which 5029 lab machine(s) your program was tested on. Be specific. Note that the submitted files must be organized in the proper hierarchy in the ZIP file.