Trying to get my first job as a developer I made an app I was extremely proud of:
https://github.com/AnatolyRudenko/Crystals.Dragons
The game starts in a random room of a random maze. Some prebuilt items get randomly located all around the maze. User can see arrows (from 1 to 4 depending on directions available to move in) and items (if there are any in current room) on his screen. You can interact with the items: pick it up, use it, drop it or destroy it. Picked up items go to inventory which is a collectionView. To win you've got find a key and open a chest with it. Any time you travel from one room to another - you lose HP.
But the feedback received on the app absolutely smashed me:
- Extremely poor realization of item pick-up. Everything is bad about that. Starting with creating an item in a room and ending with defining what item is in inventory. Items are rigidly bound to images, fixed number of items in the game.
- Items have no identifiers. Identification by name is a bad decision.
- OOP is weak. Some classes are there just for the sake of it. But neither polymorphism nor inheritance are used. Even though there are a lot of opportunities to do so.
The problem is that due to lack of experience I can't even imagine another way of building this app. The most confusing point to me is 1). But if someone could give a hint on how to fix 2) and 3), that would be much appreciated.
1)-relevant code:
Item.swift
:
struct Item {
let imageName: String
let description: String
}
ItemsList.swift
:
struct ItemsList {
var items = [
Item(imageName: K.icons.chest, description: K.descriptions.chest),
Item(imageName: K.icons.key, description: K.descriptions.key),
Item(imageName: K.icons.rock, description: K.descriptions.rock),
Item(imageName: K.icons.bone, description: K.descriptions.bone),
Item(imageName: K.icons.mushroom, description: K.descriptions.mushroom),
Item(imageName: K.icons.apple, description: K.descriptions.apple)
]
}
CurrentData.swift
:
struct CurrentData {
var itemsList = ItemsList()
var items = [Item]()
var maze: MazeGenerator
var cell: MazeElement
var size: Int
var location: (x: Int, y: Int) {
didSet {
cell = maze.maze[location.x][location.y]
}
}
var createdImages: [UIImageView] = []
var collectedImages: [(collectedIndex: Int, item: Int, image: UIImage)] = []
var itemLocationArray: [(Int, Int)] = []
var itemCollected: Int?
var collectedImagesIndex = -1
var cellSelected: Int?
init(howManyRooms: Int) {
self.size = Int(ceil(sqrt(Double(howManyRooms))))
self.location = (Int.random(in: 0...self.size-1), Int.random(in: 0...self.size-1))
items = itemsList.items
maze = MazeGenerator(self.size, self.size) //generate a maze
cell = maze.maze[location.x][location.y]
}
}
GameplayViewController.swift
:
class GameplayViewController: UIViewController {
private var current: CurrentData?
private func startGame() {
current = CurrentData.init(howManyRooms: rooms)
for index in 0...current!.items.count-1 {
createItems(imageName: current!.items[index].imageName)
let itemLocation = (Int.random(in: 0...current!.size-1), Int.random(in: 0...current!.size-1)) //Every item gets random location
current?.itemLocationArray.append(itemLocation)
}
}
private func createItems(imageName: String) { //Create item images when launched
let imageNamePNG = "\(imageName).png"
let itemImage = UIImage(named: imageNamePNG)
let itemImageView = UIImageView(image: itemImage)
if let freeSpace = self.freeSpace {
itemImageView.frame = CGRect(
x: Int.random(in: Int(freeSpace.minX) ... Int(freeSpace.maxX)), //item images can't cover arrows or inventoryView
y: Int.random(in: Int(freeSpace.minY) ... Int(freeSpace.maxY)),
width: 63, height: 63)
}
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(imageTapped(tapGestureRecognizer:)))
itemImageView.isUserInteractionEnabled = true
itemImageView.addGestureRecognizer(tapGestureRecognizer) //item image can be tapped
view.addSubview(itemImageView)
current?.createdImages.append(itemImageView)
}
@objc func imageTapped(tapGestureRecognizer: UITapGestureRecognizer) { //item gets tapped
let tappedImageView = tapGestureRecognizer.view as! UIImageView
if let tappedImage = tappedImageView.image {
if tappedImageView != current!.createdImages[0] { //can't pick up the chest
tappedImageView.isHidden = true
tappedImageView.isUserInteractionEnabled = false
current?.collectedImagesIndex += 1 //keep track of the order in which we pick up the items
current?.itemCollected = current!.createdImages.firstIndex(of: tappedImageView) //find out what item was picked
if let whatItem = current!.itemCollected {
current?.collectedImages.append((current!.collectedImagesIndex, whatItem, tappedImage))
}
collectionView.reloadData()
} else {
descriptionLabel.text = current!.items[0].description //if chest was tapped
}
}
}
}
// MARK: - UICollectionViewDataSource protocol
extension GameplayViewController: UICollectionViewDataSource, UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return current?.collectedImages.count ?? 0
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: K.Cell.reuseIdentifier, for: indexPath as IndexPath) as! CollectionViewCell
cell.inventoryImageView.image = current?.collectedImages[indexPath.item].image
return cell
}
// MARK: - UICollectionViewDelegate protocol
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
for image in current!.collectedImages {
if indexPath.item == image.collectedIndex {
descriptionLabel.text = current?.items[image.item].description
current?.cellSelected = indexPath.item
}
}
}
}
Any help is much appreciated! Thanks