Thursday, April 7, 2016

Swiftly Learning: Mini-Combat Part 3: I don't Git it

I've been saving my work on Mini Combat to github, as I may have previously mentioned. It's fairly straightforward, probably because I've spent so much time playing RPGs like Oblivion, Skyrim, and even The Sims. I'd always have my main game where I did everything the right way; picked the good guy choices, let the NPCs live, didn't set my Sims on fire. Every once in a while, though, one of the NPCs would be a little too lippy or my Sim would have a chance to do something risky like fixing a computer while standing in a puddle of water... so I'd create a special save. It was my "this is what we go back to if this goes horribly wrong" save and it was usually just a 1 tacked onto the end of my normal file name.

I think of git the same way. I don't know if I'm supposed to or not, but I do, and it makes sense to me. I do some work, I check the work in when I'm at a nice point where something's finished, and then I have a whole different sequence of saves for when I decide maybe my Sim WAS better off quitting his job, or have the original one to go back to if it all goes horribly wrong. Which is exactly what happened today.

See, as I've mentioned previously, I know my code for Mini-Combat is a mess. I have pretty much everything in my ViewController.swift file, which is, well, sloppy. It works, though, it does almost everything I want it to do. I have one last thing to add - a "restart game" button. Then, it's functionally finished! YES!!

Of course, before I did that one last thing, I got the idea in my head that I should clean it up; try to get everything working using the proper MVC pattern that I learned about on the internet. I started moving things around, putting variables in the data part and moving functions from ViewController into a Game class and started rewriting everything to reference the new stuff and and and and and...

Yeah... I'm not doing that now. I tried, and while I could absolutely do it, it was taking far more time than I want to put into something that is just a learning exercise. I'll take the lesson as this: If you're going to do it properly, do it properly from the start, because rewriting everything later is a giant pain in the arse. Glad I had that saved game to go back to.

Now, if only I could figure out how to go load my save... to Google!

Saturday, April 2, 2016

Swiftly Learning: Mini Combat Part 2: My, what a mess I've made

I finally got everything in Mini Combat working the way I wanted. The text updates, the buttons are disabled for a moment after you attack so you can't just spam the other guy to death, and there's an X WINS! label that updates when someone wins. Kinda cool for what it is, and how noob I am :)

Invisible reader, you may recall in Part 1 where I mentioned that I was breaking rules about repeating myself and filling up my ViewController with all of the things. Well, tonight I started correcting those mistakes.

The biggest challenge for me has been thinking differently. I started with this code that lived in the ViewController and totally worked GREAT:
    @IBAction func onPlayerButtonPressed(sender: UIButton) {
       let d20 = Int(arc4random_uniform(19) + 1)
       let d6 = Int(arc4random_uniform(5) + 1)
            
       player.tryAttack(monster, attackStrength: d6, hitRoll: d20)
       blueLabelText.text = player.combatStatus
        
       brownButton.enabled = false
       brownButtonTimer()
       isThereAWinner()
So yeah - worked great, you'd press the button and things would happen. Problems here, though, were:
a) I had to repeat the dice stuff for each button because doing it once in the beginning was not working, the number wouldn't change.
b) I had to repeat the brownButton stuff for each button but with different names - in my onMonsterButtonPressed, I have the same shit but with 'blackButton' instead. It's just bad mmakay, even a noob like me knows that's messy.
c) it looks sloppy and confused. Almost like.. someone just tossed it in there and didn't know what they were doing. Oh wait... ;)

To fix this, I created a class (in its own file) and called it Game. I don't know if that's the right way to do it but it seemed pretty legit at the time.  I added the dice as private vars and tried to recreate the method in a more generic way. Here's what I have so far. I'm not done but I'm tired and it's time to stop!
    func performAttack(attacker: Character, target: Character, button: UIButton) {
        attacker.tryAttack(target, attackStrength: attacker.attackPower, hitRoll: d20)
        button.enabled = false
    }
This... might work. It should work. I think. We'll see. I got this far and realized it might be really silly having both tryAttack and performAttack so I am going to try and combine them tomorrow. Problem there is that I'm not sure where the resulting creature should reside - maybe under Game? It seems controllery to me so it is not going back into the ViewController. I don't know, I'm still a noob. I need to read more before I can state any of this with any sort of confidence!

I am, however, entirely confident that I'm exhausted and will have better results tomorrow.

Friday, April 1, 2016

Swiftly Learning: Mini Combat Part 1: NSTimer

Mini Combat. Pretty exciting stuff. Two dudes, two buttons, a few lines of text, a few more lines of code making them all do things. You can view it here, if you like! 

This was my solution to an exercise in Mark Price's iOS 9 and Swift 2: From Beginner to Paid Professional class. In order to keep it on Github, I will need to change the graphics out from the provided ones to some of my own... or the internet's. :)

This project has me working with Classes in Swift for the first time. It's interesting, the other course I was doing suggested using Structs before Classes and then this one hasn't even mentioned Structs at all yet. I don't know which way is right, not yet. Maybe he's saving Structs for later cause they are so badass? We'll see!

The basic requirements were something like:
  • Landscape only
  • 2 characters each with HP, attack power, a name, and an attack button
  • Attack button is disabled for 3 seconds after an attack is made
  • Winner should be displayed at the end
  • Lets you restart the game
What tripped me up so far on this one was disabling the button for 3 seconds after attacking. I knew how to disable a button, and I knew I had to use an NSTimer, but actually making them work together was a huge pain.

I started out with this, which did not work:
NSTimer.scheduledTimerWithTimeInterval(3.0, target: self, selector: Selector("onPlayerButtonPressed"), userInfo: nil, repeats: false)

I knew that the Selector part had to be a function, but I couldn't figure out what function it was supposed to be. My best guess was whatever was calling for the timer. So, I tried all of them - and they all failed! Shit! I googled and googled and found lots of info about Selectors but nothing answered my question. I finally asked a friend if he could explain it and he did, in one sentence - "it's just the method name for the method that you want called when the time fires". I probably should have figured that out - but now I knew! This led me to create my little buddy, enableButton! 

The problem with enableButton is that I'm actually pretty tired and can't wrap my head around how I'm supposed to use it for both of the buttons that I have. I'm sure I'll figure that out tomorrow - but for now I'm breaking the "don't repeat yourself" rule just to get it working. (I'm also doing almost all of my shit in ViewController.swift so it's not like I'm doing anything right yet anyways!). 

Another little tidbit that I encountered while trying to figure out the NSTimer shenanigans, is that the whole Selector thing changed in Swift 2.2 which came out what, last week? I sure am glad I watched the video on devslopes.com about the Swift 2.2 changes already. Armed with that, Xcode's auto-suggest, and my new friend enableButton, I crafted this, which works as intended:

NSTimer.scheduledTimerWithTimeInterval(3.0, target: self, selector: #selector(ViewController.enableBlackButton), userInfo: nil, repeats: false)

Note the selector part - definitely different than it was:
selector: Selector("enableButton")
vs
#selector(ViewController.enableButton)

Yep. Now it works, and when my little dudes attack, they're forced to take a 3 second break before they attack again. Speaking of breaks, this one has been long enough. I'd better get back to it and try to figure out that button thing. 


Swiftly Learning

I've been trying to learn how to code for years, as anyone who knows me will know. I always had a hard time until I discovered the wondrous world of iOS. I know, I know - something like C# is more versatile and something like Java is more useful but you know what? I don't care. Not right now. Swift is easy, Swift is fun, and iOS development is what I want to do, anyways. So - Swift it is!

I have purchased a ton of classes on udemy.com for Swift / iOS / etc, and I'm currently working my way through iOS 9 and Swift 2: From Beginner to Paid Professional from Mark Price / devslopes.com. It's been great, I like his teaching style.

The exercise that I'm on right now is a little game, just two dudes smackin' each other. You know, even that is an exaggeration. It's really basic but whatever - I'm learning. A friend suggested I blog my progress (blogress?!?!) so I am. Maybe. We all know how good I am at consistently updating these things.

Anyway - you can follow along, or not, but here we go.