ldts-project-assignment-g0103 created by GitHub Classroom

Overview

LDTS_T01_G03 - Maze Conqueror

Game Description

The game consists of solving procedurally generated mazes as fast as possible while avoiding any obstacles in your path. Obstacles such as complicated paths, enemies and the impending red path, which stops backtracking, all make this exciting maze solving experience unique.

This project was developed by Eduardo Correia (up201909914@fc.up.pt), José Carvalho (up202005827@fc.up.pt) and Alberto Serra (up202103627@fe.up.pt) for LDTS 2021-22.

Screenshots / Gifs

The following screenshots illustrate and gifs the general look of our game, as well as the divergent functionalities:

More screenshots and diagrams can be found in the documentation.

Start Menu

img

Playing the game

img

Pause menu

img

Finishing the game

img

Shop Menu

img

Leaderboard Menu

img

Instructions Menu

img

Implemented Features

Main Menu

This section is in regard to the menu the player sees and interacts with when he starts up the game.

  • Start Game - Allows the player to start the game.
  • Instructions - Opens a new screen with info on how to play the game.
  • Exit - Closes the game.

Core Game

This section details the features of the core gameplay.

  • Maze Generation - Creates a new random maze with a reachable ending everytime the game is started.
  • Movement - Allows the player to move the hero character.
  • Collision - Prevents the player from phasing through unwanted elements of the game.
  • Trophy - Reachable goal that dictates the ending of the game.
  • Pathing - Highlights the path that the player took.
  • Hazardous Pathing - Gradually transforms the path that the player took into a red path which, on contact, deals damage to the player.
  • Health - The player's hit points, enables the player to take damage, and on reaching 0, finishes the game.
  • Pause - Allows the player to pause the game.
  • Multithreaded Input - The game does not stop and wait for player input.
  • Refactored Menus - Hand-made menus that change the state of the game. These include, starting, pausing and finishing the game. Changed from default lanterna menu's.
  • Points - The faster you complete the maze, the higher your points. Points are also acquired whenever you enter a new empty tile or pickup a coin.
  • Coins - Randomly generated elements which, on contact give the player more points.
  • Portals - Randomly generated elements which, on contact teleport the player to another portal on the maze.
  • Increasing difficulty - Increasing difficulty level that increases as the player completes more mazes. This scaling also increases
  • the amount of points the player receives.
  • Continue Playing - Continue playing after completing the first maze (with a new randomly generated maze) in order to increase your total points. The game increases in difficulty after every level.

Pause Menu

This section details the features in regard to the pause menu.

  • Resume Game - Allows the player to resume the game.
  • Restart - Allows the player to restart the game.
  • Exit - Closes the game.

Game Over/Victory Menu

This section details the features in regard to the Game Over/Victory menu.

  • Continue - Opens the shop to restock items. And allows the player to continue playing.
  • Main Menu - Allows the player to return to the main menu.
  • Exit - Allows the player to exit the game.

Leaderboard Menu

This section details the features in regard to the Leaderboard menu.

  • Leaderboard - Highscore list that shows the best players.
  • Main Menu - Allows the player to return to the main menu.

Shop Menu

This section details the features in regard to the Shop menu.

  • Shop - Allows the player to restock resources such as bombs and health.
  • Unlockable Items - Shop gains new items available for purchase after completing a certain amount of levels
  • Main Menu - Allows the player to return to the main menu.

Planned Features

This section details the planned features for the game as a whole, that were not implemented.

  • Enemies - Enemies with random movement that deal contact damage. This feature was not implemented due to the fact that it conflicted with the gameplay we set ought to create. Enemies would only add a chaotic factor which would not be healthy to the project as a whole.

Design

General project development philosophy

Test Driven Mentality

When possible, the project was designed with the test-driven development process, which consists on software requirements being converted to test cases before software is fully developed, a and tracking all software development by repeatedly testing the software against all test cases.

The four pillars of object-oriented programming

In general, the project was designed with the four pillars of object-oriented programming in mind :

  • Encapsulation - Encapsulation is accomplished when each object maintains a private state, inside a class. Other objects can not access this state directly, instead, they can only invoke a list of public functions. The object manages its own state via these functions and no other class can alter it unless explicitly allowed.
  • Abstraction - abstraction is an extension of encapsulation. It is the process of selecting data from a larger pool to show only the relevant details to the object.
  • Inheritance - Inheritance is the ability of one object to acquire some/all properties of another object. With inheritance, reusability is a major advantage.
  • Polymorphism - Polymorphism gives us a way to use a class exactly like its parent so there is no confusion with mixing types. This being said, each child sub-class keeps its own functions/methods as they are.

The Core Game Loop

Problem in Context

The problem in question was figuring out what the game was currently doing and reacting by running code accordingly.

The Pattern

The Game class, responsible for all the interaction between classes, is defined by a Singleton Pattern, ensuring that the class only has one instance and provide a global point to access it.

Despite being considered an anti-pattern, we identified a certain relevance in implementing it in a initial state of the application. With time and taking into account the multi-threading that we planned to do, made us gradually change its structure to a single instance of the Game class propagated throughout the program through methods and parameters.

Implementation

To develop the project we decided that we were going to create a state machine for our main loop and use it to change the program's behaviour. We can switch to a different state of the application by changing the gameState variable.

Our State Machine relies on the game state or player actions to determine which state to go to next. The Main Menu functions as a default state where many actions can be performed. These can depend on previous and current inputs, as well as states.

img

Most other classes are also instantiated in this class, which makes the game class a primary reference to the other objects.

img

Consequences

The use of the Singleton in the current design allows the following benefits:

  • Easy access and modification of the only instantiated game class.

These classes can be found in the following files:

Figuring out how to represent elements in the game.

Problem in Context

In our game, multiple elements like walls, paths and the player character exist, and we had to figure out a way to represent them in a structured and efficient way.

Pattern

The main pattern applied specifically to the multiple elements was the Factory Method Pattern, which is defined by an Element interface, used to create the Class object, but lets those elements sub-classes decide which class they should instantiate.

Implementation

To resolve this issue we created the Element class which is a super class to represent all the various elements in our game. Then we stored them in various data structures (depending on efficiency). These stored structures are located on the Maze class which then handles their use and representation in the game.

img

Consequences

The use of the Factory Method Pattern in the current design allows the following benefits:

  • Easily obtain proprieties and status of all the elements present on the game.
  • Avoid code smells due to repeating the same code multiple times.
  • Can have multiple elements on the same position (which would be impossible if we represented the elements on a matrix for example).

These classes can be found in the following files:


Creating the various Menus

Problem in Context

A menu/user interface is required to interact and manipulate the games current status, for example to start the game or exit it.

Pattern

The main pattern applied specifically to the menus was the State Pattern which allows the menu object to alter its behavior when its internal state changes. The object will appear to change its class, which happens during the execution of the methods in our application.

Implementation

We implemented the following menus : Game Over, Instructions, Leaderboard, Pause, Shop, Start, and Victory that are all child classes from the parent abstract class Menu. Each menu contain several buttons that allow you to perform functions within the game.

The menu object in the game class changes its behaviour depending on what state the game is running. This allows the application to simply change states and load a new menu depending on the user's needs.

Every class present on the submenu package only contains code that instantiates buttons, and text elements (both child classes of GenericMenuElement) on specific positions. The functional methods are present in the abstract class Menu.

img

Consequences

  • Creating the submenu package allows easy creation of new menus

The use of the State Pattern in the current design allows the following benefits:

  • Localizes and partitions behavior for different states.
  • Makes state transitions explicit.

These classes can be found in the following files:

Creating Buttons for use in the menus

Problem in context

After creating the menus we needed to create buttons which allowed the player to interact with the application.

Pattern

The main patterns applied specifically to the buttons was the Factory Method Pattern, which is defined by a Button interface, used to create the Class object, but lets those elements sub-classes decide which class they should instantiate, and the Strategy Pattern which defines a family of algorithms, like the execute method, encapsulates each one and makes them interchangeable.

The use of this patterns allows the elimination of an abusive amount of conditional statements, preventing future bugs or code smells like switch statements.

Implementation

To resolve this issue we created the Button abstract class which is a parent class to all the buttons, , with a protected constructor.

This class implements the ButtonInterface Interface which contains the execute() method (among others).

The execute() function is called whenever the user presses enter on a selected button. This function is only actually implemented in the child classes of Button which allows each button to have different behavior on execution while still re-using most of the implementation.

img

Consequences

The use of the Factory Method Pattern in the current design allows the following benefits

  • Easy creation of new buttons
  • Easily obtain proprieties and status of all the buttons
  • Avoid code smells due to repeating the same code multiple times.

The use of the Strategy in the current design allows the following benefits:

  • Eliminates conditional statements.
  • Provides different implementations.

These classes can be found in the following files:

Handlers

Problem in context

Certain classes such as Maze and Game were responsible for handling code that they should not. So handler classes were created for implementing code relating to managing their respective objects.

This type of implementation tends to avoid code smells like large class and long parameter lists.

Implementation

Each handler is initialized in either the Maze or Game Class and is used to manipulate the properties and aspects of their respective objects.

Aspects such as hero health and portal interaction are all done through these handlers.

Consequences

  • Cleaner Maze and Game classes.
  • Able to maintain values after creating a new instance of Maze

This class can be found in the following file:

Leaderboard

Problem in context

After completing a game, the current user id and points need to stored for later use.

Implementation

Every time the Game class is initialized (once per application startup) a user id is given based on the highest id on the data/leaderboard.txt file.

During application startup the data in the file is read and put on a TreeMap<Integer,Integer> which holds the player id as a key and their respective points in the value.

After inserting the values into the map, this map is sorted by value so that we can simply get the first 10 values whenever we want to load the leaderboard.

After winning a game, (specifically whenever a player clicks on the exit or main menu button) the leaderboard writes the current score and id to the data/leaderboard.txt file.

This class can be found in the following file:

Shop

Problem

Create a shop where the player can restock and buy resources after completing a game.

Implementation

Every action is possible with a single call the functions such as sell(), increaseStock()andgeneralReStock().

Every item in the shop can have a custom icon, name,price and an optional maximum value.

These items will only be available for sale the player meets the requirements for purchasing said item , for example to restore health the player must have the correct amount of points and the player's current health needs to be lower than the maximum allowed.

When the player reaches level 10, the shop unlocks new items for sale and the previous listed items will be restocked.

This class can be found in the following file:

Maze/Other

Maze Representation

To generate a new maze, we use the MazeGenerator class, which gives us an integer matrix of 0's and 1's, that we then use to create the elements needed for the game.

All static elements present in the game are also stored in the Maze class.

Data structures

Generally speaking whenever an element needed to be stored we tried to use the most efficient data structure for that situation. With that said we usually opted to store elements in a Linked List instead of an Array List.

Justification

Operation Linked List Array List
add O(1) O(n)
remove O(n) O(n)
get O(n) O(1)

Knowing this table, the fact that we don't know, index wise, where elements are stored (which makes the get() method irrelevant) and the fact that we are always inserting new elements into the structure, the obvious choice was the Linked List structure.


Deprecated

This section list features that were implemented but were not used in the final application.

Keyboard Listener

This class was created with the intention of running on a different thread and reading the user's input as to not stop the rest of the application's execution. However, this class was eventually replaced with the lanterna.pollInput() method which essentially did the same thing.


Known code smells/problems and refactoring suggestions.

This section list code smells and problems that we could identify in our application.

Design problems

Using a single threaded code-flow

While discussing the project, the question of whether we should use a multithreaded approach was brought up.

At the beginning we thought this would be inevitable, due to the fact that the lanterna getInput() method interrupts the processing of the code, much like a system input function. So we developed a KeyboardListener class which would run on a separate Thread. This class would queue up the inputs read from the user, without interrupting the code. We managed to circumvent this issue however, using the screen.pollInput() which essentially did the same thing.

Another instance we thought of using threads was with the handler package. The classes present within this class are currently are instantiated on the Maze and Game class.

The idea of handling certain aspects of the game in an asynchronous manner, at first did look appealing, yet this brought up the question of what would happen if established classes where modified in an unordered manner, which would wind up introducing unwanted problems. So we decided to run everything on a single, timed thread, running currently at 30 frames per second.

Wrong data structure

The Heart element is currently stored in a ArrayList, which is not as efficient as storing it in a stack, for our use case. This is due to the implementation of the remove() method in the List class which has a complexity of O(n).

Comparatively speaking, the pop() method in a Stack has a complexity of O(1).

Change the code to accept Hearts in a Stack instead of a ArrayList.


Code Smells

Large Class

Problem

Currently, the Game class is responsible for too much code, handling game elements that should be outside of its reach.

Solution

Refactor certain sections of code to be in a different class, or separate it in two.

Ex: using Extract Class


Long Method

Problem

Currently, the constructor for the Maze class is too big, which is simply due to the great amount of variables this class.

Solution

Create more functions to divide the code and make it more readable, grouping the lines of it together. This, however, would only replace the current problem with a Long Class code smell.

Ex: using Extract Method


Long Method

Problem

Currently, the constructor for the Game class is too big, which is simply due to the great amount of variables this class.

Solution

Create more functions to divide the code and make it more readable. This, however, only propagates the Large class code smell that exists within this class.

Ex: using Extract Method


Long Parameter List

Problem

Some element constructors take 4 or 5 parameters per constructor. This happens because we are taking in unnecessary arguments such as the element's character and format when we could simply have them as final variables in the class.

Solution

Change these variables to be final and initialize them outside the constructor.

Ex: using Introduce Parameter Object


Long Method

Problem

The InstructionsMenu class in the submenu package is really overwhelming size-wise because, we need to create multiple text elements in many positions which is done by creating many objects.

Solution

Create these elements in a separate data file.

Ex: using Extract Method


Feature envy

Problem

All handlers suffer from the feature envy code smell. This is because they handle and interact with objects that were initialized outside their own class.

Solution

Initialize the handled objects in these classes.

Ex: using Move Method


Switch Statements

Problem

Currently, the checkTile() function in the Maze class consists of nested if's which is not good practice for adding new features.

Solution

Change the function to a state pattern design.

Ex: using Move Method


Parallel Inheritance Hierarchies

Problem

When creating the buttons classes, we could have applied the same principle as the draw method to the elements, parameterizing the variables in the abstract class and avoiding code repetition. However, the Victory Button and Exit Button, for containing such a specific implementation, forced us to create all the other classes to make the program consistent and using Strategy Pattern.

Solution

Parameterize all the necessary variables in a common method in the abstract button super class and use if conditions for the different implementations.

Ex: using Parameterize Method


TESTING

We currently have 200 tests which give us the following coverage

img

Unit testing was the strategy chosen in order to test individual units of the game to obtain the expected behavior of the application. To achieve this purpose, the use of JUnit and Jqwik was fundamental.

Overall, the team chose to focus on massive testing and later, with the application of some Property Based Testing concepts, allowed the end result to be a very complete test suite with good coverage.

This observable coverage could be even better numerically if we removed the classes that are not in use, but we considered them relevant to demonstrate a possible future or alternative implementation in our application.

Most of the code lines not covered were due to draw methods, where it was preferable to check through mocks if they were executed instead of their behavior since they do not contain methods created by us.

Self-Evaluation

  • Eduardo Correia: 33.3%
  • José Carvalho: 33.3%
  • Alberto Serra: 33.3%
You might also like...

HUAWEI 3D Modeling Kit project contains a sample app. Guided by this demo, you will be able to implement full 3D Modeling Kit capabilities, including 3D object reconstruction and material generation.

HUAWEI 3D Modeling Kit Sample English | 中文 Introduction This project includes apps developed based on HUAWEI 3D Modeling Kit. The project directory is

Jan 1, 2023

Example of using the TestFX library to perform E2E tests in a Maven project

demoTestFX Ejemplo de uso de la librería TestFX para realizar pruebas E2E en un proyecto Maven. El principal problema para conseguir ejecutar los test

Jan 28, 2022

ITI TicTacToe Server project

TicTacToeClient ITI TicTacToe Client project Steps Clone project Create local branch name Development command git branch Development Checkout to the D

Jan 27, 2022

The goal of this project is to create AssertJ assertions for JavaFX (8).

The goal of this project is to create AssertJ assertions for JavaFX (8).

Jul 30, 2021

JavaFX with CDI example project

JavaFX with CDI example project

javafx-cdi-example JavaFX with CDI example. ⚠️ In case you have a hi-resolution display and want to run the application on Ubuntu, make sure to pass a

Aug 4, 2022

OOP course final project - Group: Leon Baiocchi, Federico Brunelli, Alessandro Pioggia, Luca Rengo

OOP course final project - Group: Leon Baiocchi, Federico Brunelli, Alessandro Pioggia, Luca Rengo

Bullet Ballet Bullet Ballet is a 2D platformer developed for a University Project at the Alma Mater Studiorum of Bologna by Leon Baiocchi, Alessandro

Dec 8, 2022

Project for "Software Engineering" Course, University of Macedonia (UoM).

CovIDetect CovIDetect is a dashboard application for universities that aims to facilitate the process of managing covid cases and provide statistical

Dec 21, 2022

course-project-real-estate-finder-004 created by GitHub Classroom

Real Estate Finder Running the Project: Clone the repository and open with IntelliJ IntelliJ may not correctly open the project on the first run, but

Dec 16, 2021

group-project-team1 created by GitHub Classroom

Team 1 Timothy Flucker Hello my name is Timothy Flucker and I am a software developer consultant at Deloitte. I have 8 years of software development e

Nov 10, 2022

course-project-javajsk created by GitHub Classroom

Project JavaJSK - UofTruck University of Toronto Food truck ordering system. For more information see our design document. Problem specification Our p

Jan 12, 2022

hello-git-taqiyaehsan created by GitHub Classroom

👋 The Basics of GitHub 🤓 Course overview and learning outcomes The goal of this course is to give you a brief introduction to GitHub. We’ll also pro

Feb 3, 2022

☕️🚀🚨 This repository consists of solutions for the Community Classroom complete DSA Java Bootcamp assignment problems.

Java DSA Bootcamp 🌐 Assignments Go to Kunal Kushwaha's 👨🏻‍💻 course repository : ☕️ Java DSA Bootcamp ⚠️ 🚨 this repository is now inactive due to

Dec 12, 2022

Section B of Assignment 1. Setup project and collaborate on GitHub by writing test fixtures.

Section B of Assignment 1. Setup project and collaborate on GitHub by writing test fixtures.

Task Each member (including the team leader) should create a branch (use student number as the branch name) and include a small program in the branch

Apr 6, 2022

GitHub Search Engine: Web Application used to retrieve, store and present projects from GitHub, as well as any statistics related to them.

GHSearch Platform This project is made of two subprojects: application: The main application has two main responsibilities: Crawling GitHub and retrie

Nov 25, 2022

GithubReleases4J - GitHub Releases for Java , based on GitHub RESTful API .

GithubReleases4J - GitHub Releases for Java , based on GitHub RESTful API .

Jun 27, 2022

Chess made as an assignment project for OOP course 2021/22

Chess made as an assignment project for OOP course 2021/22

chess Chess made as an assignment project for OOP course 2021/22 Installation Project is built with Clone the repository In the directory containing p

May 1, 2022

This repository consists of the code samples, assignments, and the curriculum for the Community Classroom complete Data Structures & Algorithms Java bootcamp.

DSA-Bootcamp-Java Subscribe to our channel Complete Playlist Syllabus Discord for discussions Telegram for announcements Connect with me     Follow Co

Jan 1, 2023

Android App for Classroom Interaction

Android App for Classroom Interaction

即時課堂互動 Classroom Interaction App (畢業專題 2017) 指導教授: 趙一芬 組員: 許宸瑜, 謝子晏, 范植貿, 周易凱 Poster: png Report: word Slides: pdf 專題動機 : 往往電機系給人的印象是半導體、IC設計,而近年來,因為資

Feb 13, 2022
Owner
Eduardo Correia
Eduardo Correia
Old and archived; More recent development is in https://github.com/Create-Fabric/Create-Refabricated.

NOW ARCHIVED Go here for the continuation of this project. Old README Create Fabric A Fabric port of Create. Create Discord: https://discord.gg/AjRTh6

null 12 Dec 7, 2022
PS4 Remote PKG Installer GUI for https://github.com/flatz/ps4_remote_pkg_installer

PS4 Remote PKG Installer PS4 Remote PKG Installer GUI for https://github.com/flatz/ps4_remote_pkg_installer Tired of copying PKG files to USB then wal

Benjamin Faal 116 Dec 25, 2022
InstallRepos - Install GitHub Repository on any Operating System (Linux, MacOS or Windows).

Install Repos Install GitHub Repository on any Operating System (Linux, MacOS or Windows). Requires Java JRE 17.0.0.1 or later. Repository Includes: s

Tushar Chaurasia 2 Apr 21, 2022
Ribbon control for Java, created in JavaFX

FXRibbon Ribbon control for Java, using JavaFX framework, based on Microsoft Ribbon. If you want to support the development of this library consider a

Pedro Duque Vieira 224 Dec 27, 2022
😉PrettyZoo is a GUI for Zookeeper created by JavaFX and Apache Curator Framework.

?? Pretty nice Zookeeper GUI, Support Win / Mac / Linux Platform

vran 2.4k Jan 5, 2023
Lib-Tile is a multi Maven project written in JavaFX and NetBeans IDE 8 and provides the functionalities to use and handle easily Tiles in your JavaFX application.

Lib-Tile Intention Lib-Tile is a multi Maven project written in JavaFX and NetBeans IDE and provides the functionalities to use and handle easily Tile

Peter Rogge 13 Apr 13, 2022
To quickly integrate your applications into the EdgeGallery platform, we provide the toolchain project to help developers quickly modify code and migrate applications to the platform.

Toolchain 工具链 工具链是MEC Developer开发者平台中的一个重要特性,当x86平台的App想要上车ARM平台时,底层的代码不可避免的需要进行修改或重写。 App提供者可以通过MEC Developer开发者平台中集成的工具链进行源代码分析,定位需要修改的源代码并根据指导意见进行修

EdgeGallery 19 Jan 7, 2022
A project that shows the different ways on how to create custom controls in JavaFX

JavaFX Custom Controls This project will show different ways on how to create custom controls in JavaFX. It will cover the following approaches: Resty

Gerrit Grunwald 27 Sep 5, 2022
In the Developer - Platform of EdgeGallery, we have provided a lot of useful APIs, in this project, try to simulates APIs of the competence center to help develoers test API request and response online.

api-emulator api-emulator模块,为EdgeGallery提供了基本能力的模拟api,开发者可以调用该模拟器提供的api,不需要真实部署就可以查看平台已有的能力。目前该api-emulator集成了两种平台能力:位置服务和人脸识别能力。 平台能力简介 位置服务 提供用户位置,E

EdgeGallery 21 Dec 25, 2021
A template project for Keycloak Customizations

Keycloak Project Example Introduction This repository contains a project setup for keycloak based projects. This setup serves as a starting point to s

Thomas Darimont 206 Jan 4, 2023