关键词 > CSSE1001/CSSE7030

CSSE1001/CSSE7030 Farm Game Assignment 3 Semester 1, 2022

发布时间:2023-05-13

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

Farm Game

Assignment 3

Semester 1, 2022

CSSE1001/CSSE7030

Due date: 26th May 2023 16:00 GMT+10

1 Introduction

In Assignment 3 you will implement a graphical user interface (GUI) for Farm Game. Farm Game is a role-playing video game in which the player runs a farm, planting and harvesting crops, tilling and untilling soil, and buying and selling seeds and produce.  An example of a final completed game is displayed in Figure 1.

Figure 1:  Example screenshot from a completed Farm  Game implementation.  Note that your display may look slightly different depending on your OS.

As opposed to earlier assignments where user interaction was handled via calls to input, user interaction in assignment 3 will occur via key-presses and mouse clicks.

Your solution will follow the Apple MVC design pattern covered in lectures. To assist you in your implementation, the model classes have been provided along with some extra support code and constants; see Section 4 for further details. You are required to implement a series of view classes as well as the controller class.

2 Setting Up

Aside from downloading and unzipping a3 .zip, to begin this assignment you will also need to install the Pillow library via pip. Instructions on how to install Pillow can be found here1.

3 Tips and hints

You should be testing regularly throughout the coding process.  Test your GUI manually and regularly upload to Gradescope to ensure the components you have implemented pass the Grade- scope tests.  Note that Gradescope tests may fail on an implementation that visually appears correct if your implementation is wrong.  You must implement your solution according to the implementation details from Section 6. Implementing the game using your own structure is likely to result in a grade of 0.  Note also that minor differences in your program (e.g.  a few pixels difference in widget size) may not cause the tests to fail.  It is your responsibility to upload to Gradescope early and often, in order to ensure your solution passes the tests.

This document outlines the required classes and methods in your assignment.  You are highly encouraged to create your own helper methods to reduce code duplication and to make your code more readable.

Except where specified, you are only required to do enough error handling such that regular game play does not cause your program to crash or error.  If an attempt at a feature causes your pro- gram to crash or behave in a way that testing other functionality becomes difficult without your marker modifying your code, comment it out before submitting your assignment. If your solution contains code that prevents it from being run, you will receive a mark of 0.

You must not add any imports; doing so will result in a deduction of up to 100% of your mark.

You may use any code provided from the teaching staff of this course in this semester only. This includes any code from the support files or sample solutions for previous assignments from this semester only, as well as any lecture or tutorial code provided to you by course staff. How- ever, it is your responsibility to ensure that this code is styled appropriately, and is an appropriate and correct approach to the problem you are addressing.

For additional help with tkinter, you can find documentation on effbot2 and New Mexico Tech3.

Figure 2: Class diagram for model .py.

4 Provided Code

This section provides a brief, high-level overview of the files provided for you in a3 .zip.  For further information, please see the documentation within each file.

4.1 model.py

The model .py file provides modelling classes for the plants and player, as well as the overall model for the game. Figure 2 presents a class diagram of the classes provided in this file. You will only need to instantiate FarmModel in your code. However, you will still be interacting with instances of the other classes via the FarmModel instance.

4.2 a3 support.py

The a3 support .py file contains support code to assist you in writing your solution. In particular, this file provides the following:

1. get plant image name(plant:    ’Plant’)  ->  str: a function to help map between Plant objects and the names of their corresponding image files.

2. get image(image name:    str,  size,  cache=None)  ->  Image:  a function to create, re- size, and optionally cache images based on the name of their image file. Returns the image object, which can be rendered onto a tkinter Canvas. Note: you need to retain refer- ences to either all the images, or to the cache. Tkinter will delete an image as soon as all references to it have been lost. Note also: use of this function in creating images is mandatory.

3. read map(map file:    str)  ->  list[str]:  Reads a map file into a list of strings, where each string represents one row of the map.  The first item represents the top row, and the last item represents the bottom row.

4. AbstractGrid: AbstractGrid is an abstract view class which inherits from tk .Canvas and provides base functionality for multiple view classes. An AbstractGrid can be thought of as a grid with a set number of rows and columns, which supports creation of text and shapes at specific (row, column) positions. Note that the number of rows may differ from the number of columns, and may change after the construction of the AbstractGrid.

4.3 constants.py

The constants .py file contains a set of constants that will be useful in implementing your as- signment. Where a detail is not specified in this document (e.g. size or colour of a widget, etc.), please refer to constants .py.

5 Recommended Approach

As opposed to earlier assignments, where you would work through the task sheet in order, develop- ing GUI programs tends to require that you work on various interacting classes in parallel. Rather than working on each class in the order listed, you may find it beneficial to work on one feature at a time and test it thoroughly before moving on. Each feature will require updates / extensions to the controller, and potentially additions to one or more view classes. The recommended order of features (after reading through all of Section 6 of this document) are as follows:

1. play game, main, and title: Create the window, ensure it displays when the program is run and set its title.

2. Title banner: Render the title banner at the top of the window.

3.  InfoPanel and Next day button (including being able to increment the day on the info panel).

4. FarmView:

• Display basic map from file.

• Display and move player.

Till and untill soil.

5.  ItemView:

• Basic display (non-functional)

• Binding command for selecting item.  After this is implemented, you can implement planting, removing plants, growth of plants on a new day, and harvesting.

• Binding commands for buying and selling items.

6 Implementation

You must implement three view classes; InfoBar, FarmView, and ItemView.  Additionally, you must implement a controller class - FarmGame - which instantiates the FarmModel and all three view classes, and handles events.

This section describes the required structure of your implementation, however, it is not in- tended to provide an order in which you should approach the tasks. The controller class will likely need to be implemented in parallel with the view classes. See Section 5 for a recommended order in which you should approach this assignment.

6.1 InfoBar

InfoBar should inherit from AbstractGrid (see a3 support .py). It is a grid with 2 rows and 3 columns, which displays information to the user about the number of days elapsed in the game, as well as the player’s energy and health. The InfoBar should span the entire width of the farm and inventory combined. An example of a completed InfoBar in the game is shown in Figure 3. The methods you must implement in this class are:

init (self, master:   tk .Tk  |  tk .Frame)  ->  None:  Sets up this InfoBar to be an AbstractGrid with the appropriate number of rows and columns,  and the appropriate width and height (see constants .py).

• redraw(self,  day:    int, money:    int,  energy:    int)  ->  None: Clears the InfoBar and redraws it to display the provided day, money, and energy. E.g. in Figure 3, this method was called with day = 1, money = 0, and energy = 100.

Figure 3: InfoBar after redrawing with information from a new FarmModel.

6.2 FarmView

FarmView should inherit from AbstractGrid (see a3 support .py).  The FarmView is a grid dis- playing the farm map, player, and plants.  An example of a completed FarmView is shown in Figure 4. The methods you must implement in this class are:

init (self, master:   tk .Tk  |  tk .Frame,  dimensions:   tuple[int,  int],  size: tuple[int,  int],  **kwargs)  ->  None:  Sets up the FarmView to be an AbstractGrid with the appropriate dimensions and size, and creates an instance attribute of an empty dictionary to be used as an image cache.

• redraw(self,  ground:    list[str], plants:   dict[tuple[int,  int],  ‘Plant’], player position:   tuple[int,  int], player direction:    str)  ->  None:

Clears the farm view, then creates (on the FarmView instance) the images for the ground, then the plants, then the player. That is, the player and plants should render in front of the ground, and the player should render in front of the plants. You must use the get image function from a3 support .py to create your images.

6.3 ItemView

ItemView should inherit from tk .Frame. The ItemView is a frame displaying relevant information and buttons for a single item. There are 6 items available in the game (see the ITEMS constant in constants.py).  The ItemView for an item should contain the following widgets, packed left to right:

• A label containing the name of the item and the amount of the item that the player has in their inventory, the selling price of the item, and the buying price of the item (if the item can be bought; see BUY PRICES in constants .py).

• If this item can be bought, the frame should then contain a button for buying the item at the listed buy price.

• A button for selling the item at the listed sell price (all items can be sold).

There are three kinds of events that can occur on the ItemView: a left click on an items frame or label (indicating that the user would like to select the item), a button press on a buy button (indicating that the user would like to buy one of those items), and a button press on the sell

Figure 4: Example of a FarmView partway through a game.

button (indicating that the user would like to sell one of those items).  The callbacks for these buttons must be created in the controller (see FarmGame) and passed to each ItemView via the constructor.

The methods that you must implement in this class are:

init (self, master:   tk .Frame,  item name:    str,  amount:    int,  select command: Optional[Callable[[str],  None]]  =  None,  sell command:    Optional[Callable[[str], None]]  =  None, buy command:    Optional[Callable[[str],  None]]  =  None)  ->  None :     Sets up ItemView to operate as a tk .Frame, and creates all internal widgets. Sets the com-      mands for the buy and sell buttons to the buy command and sell command each called with      the appropriate item name respectively.  Binds the select command to be called with the      appropriate item name when either the ItemView frame or label is left clicked. Note: The      three callbacks are type-hinted as Optional to allow you to pass in None if you have not yet      implemented these callbacks (i.e. when developing, just pass None to begin with, and hook      up the functionality once you’ve completed the rest of the tasks; see Section 5).

• update(self,  amount:    int,  selected:   bool  =  False)  ->  None :  Updates the text on the label, and the colour of this ItemView appropriately.  See Figure 5 for more details on how these are presented. Note: you should configure the existing widgets in this method. You must not destroy and recreate the internal widgets.

Note: Handling callbacks is an advanced task. These callbacks will be created within the controller class, as this is the only place where you have access to the required modelling information. Start this task by trying to render the ItemViews correctly, without the callbacks. Then integrate these views into the game, before working on the select command. Once items can be selected from the inventory, work on planting, growing and removing plants. It is recommended that you leave the buying and selling functionality until the end of the assignment.

Figure  5:   Example of all 6  ItemView instances in the overall game.   Note:  some operating systems will retain the default background colour behind buttons. While you will not be marked down for this, if you would like to set the colour behind the buttons, you can do so via the highlightbackground kwarg.

6.4 FarmGame

FarmGame is the controller class for the overall game. The controller is responsible for creating and maintaining instances of the model and view classes, event handling, and facilitating communi- cation between the model and view classes. Figure 1 provides an example of how the FarmGame should look. Certain events should cause behaviour as per Table 1. The methods that you must implement in this class are:

init (self, master:   tk .Tk, map file:    str)  ->  None: Sets up the FarmGame. This includes the following steps:

Set the title of the window.

Create the title banner (you must use get image).

Create the FarmModel instance.

Create the instances of your view classes, and ensure they display in the format shown in Figure 1.

Create a button to enable users to increment the day, which should have the text ‘Next day’ and be displayed below the other view classes. When this button is pressed, the model should advance to the next day, and then the view classes should be redrawn to reflect the changes in the model.

Bind the handle keypress method to the ‘<KeyPress>’ event.

Call the redraw method to ensure the view draws according to the current model state.

• redraw(self)  ->  None: Redraws the entire game based on the current model state.

• handle keypress(self,  event:   tk .Event)  ->  None: An event handler to be called when a keypress event occurs.  Should trigger the relevant behaviour as per Table 1, and cause the view to update to reflect the changes.  If a key is pressed that does not correspond to an event, it should be ignored.

• select item(self,  item name:    str)  ->  None: The callback to be given to each ItemView for item selection. This method should set the selected item to be item name and then re-  draw the view.

• buy item(self,  item name:    str)  ->  None: The callback to be given to each ItemView for buying items. This method should cause the player to attempt to buy the item with the given item name, at the price specified in BUY PRICES, and then redraw the view.

• sell item(self,  item name:    str)  ->  None: The callback to be given to each ItemView for selling items. This method should cause the player to attempt to sell the item with the given item name, at the price specified in SELL PRICES, and then redraw the view.

Event

Behaviour

Key Press: ‘w

Player attempts to move up one square.

Key Press: ‘a

Player attempts to move left one square.

Key Press: ‘s

Player attempts to move down one square.

Key Press: ‘d

Player attempts to move right one square.

Key Press: ‘p

If an item is selected and that item is a seed, attempt to plant that seed at the players current position. If that position does not contain soil, a plant already exists in that spot, or a seed is not currently selected, do nothing.

Key Press: ‘h

Attempt to harvest the plant from the players current posi- tion. If no plant exists at the players current location, or the plant is not ready for harvest, do nothing. If the harvest is successful, add the harvested item/s to the players inventory, and if the plant should be removed on harvest, remove the plant from the farm.

Key Press: ‘r

Attempt to remove the plant from the players current posi- tion. Note that this does not harvest the plant, and does not require the plant to be ready for harvest. If no plant exists at the players currently location, do nothing.