This is java project. The instruction is quite long, so please read carefully to fully implement the requirements of the project. Also, at the end of the instructon there is Extra Features for extra credit, I also need you to help me this
You should use IntelliJ for this exercise because I am using this software. Once done, please help me write a writeup showing me how to setup and run this project on IntelliJ
CSC 413 Term Project San Francisco State University CSC 413: Software Development Dawson Zhou (
[email protected]) Term Project Overview The goal of the term project is to apply design principles we’ve learned throughout the semester to develop a simple video game with a focus on extensibility. Submission The term project is due on Friday, December 17, 2021 at 11:59 pm PT. Late submissions will be accepted with a penalty: ● December 18, 2021 12:00 am PT to December 18, 2021 11:59 pm PT will receive 75% ● December 19, 2021 12:00 am PT to December 19, 2021 11:59 pm PT will receive 50% Grading 100 pts total: ● 10 pts: Game control ○ 6 pts: Must transition the game to show the end menu screen if: ■ Escape key is pressed while on the run game screen ■ Player tank is destroyed ■ All AI tanks are destroyed ○ 4 pts: Restarting from the end menu screen starts a fresh new game ● 47 pts: Model elements for game entities ○ 4 pts: Supports a player tank that moves based on keyboard input ○ 8 pts: Implements at least 2 different types of AI tanks with support for multiple tanks in the game at once with separate tank movement logic ■ At least one of the AI tank types must determine its behavior on the GameWorld, e.g. where the player is, where other tanks are, where shells on the screen are, etc. ○ 5 pts: Bounds checking on tanks to prevent them from moving offscreen ○ 10 pts: Allows the player tank and the AI tanks to fire shells ○ 5 pts: Walls added to the game ○ 5 pts: Tanks and walls track their “health”, and are destroyed after taking too many hits from shells ○ 10 pts: Entity classes share code between player tank, AI tanks, shells, and walls ● 18 pts: Collision detection and handling ○ 6 pts: Collisions are correctly detected ○ 12 pts: Collisions are correctly handled ● 15 pts: Additional features (see Extra Features below) ● 10 pts: Miscellaneous (model and view code kept separate, various style issues, etc.) ● (extra credit) 10 pts: Extra credit for additional features beyond the initial 15 points (see Extra Features below) Assignment Setup Click on the GitHub Classroom link provided on iLearn to automatically create your GitHub repository for the assignment, which will include the starter code for the project. See the “Git, GitHub, and IntelliJ Setup Guide” document for instructions on setting up the rest of the project on your local machine. In addition to those instructions, you’ll also need to indicate to IntelliJ that there are images in the “resources” folder. You can do so by right-clicking the “resources” directory in the project navigation panel on the left and selecting “Mark Directory as” > “Resources Root”, as shown below. Detailed Requirements Understanding the Starter Code The first major step to tackling the project is to spend some time reading over the provided starter code to understand what is already implemented, and what classes you’ll need to interact with. The classes provided include the following: ● GameDriver.java: The controller of our game. This is where the main method is defined as the entry point of the program. GameDriver defines the gameplay loop which drives the game. You are responsible for implementing the setUpGame, updateGame, and resetGame methods. ● KeyboardReader.java: The class responsible for understanding keyboard input. The KeyboardReader is provided to you as a singleton class. You can ask its instance if a key is currently being pressed. You won’t need to modify this class, unless you decide to add an extra feature that requires additional key input. ● WallInformation.java: A convenient way to package information you need about walls. See Walls below for more details on how to use the class. ● Constants.java: Various useful constant values. ● model/Tank.java: A basic version of a model class that can be used to represent tanks. You will need to add classes for other entity types, and find ways to reduce code duplication between them. ● model/GameWorld.java: The class tracking all entities present in the game world. You will be defining and implementing methods so that any other code in the project which needs to access the various entities in the game world can do so. ● view/RunGameView.java: The view class that you’ll be interacting with to draw images on screen. You won’t need to modify this class, but you will be calling its various public methods. ● view/
: Other classes controlling the UI aspects of the game. This code is provided to you, and won’t need to be modified. Tanks Every entity in the game will have two aspects to its representation: the model object, and the view sprite. The model object will be defined by a class in the edu.csc413.tankgame.model package, and the corresponding sprite in the view will share its String id. To start with, focus on adding two tanks to the game. The GameWorld will track the tank model objects, while the RunGameView will track their corresponding sprites. Once you’re able to display the two tanks on screen, work on implementing movement logic: one as a player tank responding to keyboard input, and one as an AI tank determining its own movement logic. See Lecture 25 for more details. Shells Once you have tanks moving around on screen, you can add the ability for tanks to fire shells. There are a few key observations that will help us determine how to add shells: ● Player tanks fire shells based on keyboard input (when the spacebar is pressed), while AI tanks fire shells based on their movement logic. ● When a shell is created, its starting position and angle are based on the tank that fired it. ● A shell moves in a straight line, maintaining a constant angle, until it goes off screen. A design that suits all of the requirements is to define a Shell class for shell entities which tracks their position and angle. A shell can move each iteration of the gameplay loop, just like a tank, so you will want to find a way to share code between the two -- I strongly recommend defining an abstract Entity class which contains code common to both. When a tank shoots a shell, a Shell object needs to be created and added to the GameWorld. Since tanks determine when to shoot shells in their .move(...) methods, they will need to have access to the GameWorld so they can create and add the Shell. Keep this in mind when implementing the .move(...) method for entities: you will need to pass the GameWorld in as a parameter. There’s an additional problem when a shell is fired -- even once we’ve found a way to add the new Shell entity to the GameWorld, it won’t have a corresponding sprite added to the RunGameView, so we won’t see its image on screen. We don’t want the tank .move(...) logic to be responsible for adding the sprite as well, because it violates the Separation of Concerns principle: model logic shouldn’t be directly dealing with view logic. What we can instead do is record in the GameWorld that there is a brand new Shell entity, and a corresponding sprite needs to be added as well. After all existing entities are done moving, the main gameplay loop in GameDriver can then add the corresponding sprites for all of those new shells. See Lecture 26 for more details. GameWorld Aware AI Tank Logic You are required to have at least two different types of AI tanks, with both being on screen at the same time. At least one of those AI types must base its .move(...) logic on information about the GameWorld, such as the player’s current location. The following is some logic I used during in-class demos that will cause an AI tank to always be turning so that they face the player tank. You may feel free to use this code within your .move(...) logic for a GameWorld aware AI tank. Entity playerTank = gameWorld.getEntity(Constants.PLAYER_TANK_ID); // To figure out what angle the AI tank needs to face, we'll use the // change in the x and y axes between the AI and player tanks. double dx = playerTank.getX() - getX(); double dy = playerTank.getY() - getY(); // atan2 applies arctangent to the ratio of the two provided values. double angleToPlayer = Math.atan2(dy, dx); double angleDifference = getAngle() - angleToPlayer; // We want to keep the angle difference between -180 degrees and 180 // degrees for the next step. This ensures that anything outside of that // range is adjusted by 360 degrees at a time until it is, so that the // angle is still equivalent. angleDifference -= Math.floor(angleDifference / Math.toRadians(360.0) + 0.5) * Math.toRadians(360.0); // The angle difference being positive or negative determines if we turn // left or right. However, we don’t want the Tank to be constantly // bouncing back and forth around 0 degrees, alternating between left // and right turns, so we build in a small margin of error. if (angleDifference < -math.toradians(3.0))="" {="" turnright(constants.tank_turn_speed);="" }="" else="" if="" (angledifference=""> Math.toRadians(3.0)) { turnLeft(Constants.TANK_TURN_SPEED); } If you do use the above code in your implementation of an AI tank, you must add some additional movement logic of your own to receive full credit. Bounds Checking We need bounds checking to deal with tanks and shells going off screen. It’s fairly straightforward to determine if an entity is off-screen -- we just check if its x coordinate is less than the minimum x allowed or greater than the maximum x allowed for that entity, and likewise for its y coordinate. The minimum and maximum x and y values allowed are provided for tanks and for shells in the Constants class. The type of entity determines what should happen next if the entity is found to be off-screen. ● A tank that is off-screen should have its location updated so that it is back on-screen. ○ If the x coordinate is less than Constants.TANK_X_LOWER_BOUND, it should be set to Constants.TANK_X_LOWER_BOUND. ○ If the x coordinate is greater than Constants.TANK_X_UPPER_BOUND, it should be set to Constants.TANK_X_UPPER_BOUND. ○ If the y coordinate is less than Constants.TANK_Y_LOWER_BOUND, it should be set to Constants.TANK_Y_LOWER_BOUND. ○ If the y coordinate is greater than Constants.TANK_Y_UPPER_BOUND, it should be set to Constants.TANK_Y_UPPER_BOUND. ● A shell that is off-screen should be removed from the GameWorld. ○ To receive full credit, the shell’s corresponding sprite must also be removed from the RunGameView. To do this, when you remove the shell from the GameWorld, you’ll need to “remember” it later on so that you can also remove its sprite from the RunGameView. ○ Tracking which shells need to be removed can also make it simpler to add animations such as a small