Thursday, February 04, 2021

Flutter vs SwiftUI

It's a new year and time to make a new app.

So what do I build my new app in? SwiftUI or Flutter?

TL;DR - I'm making my new app in Flutter.

I arrived at this decision by making a vertical slice of the app using SwiftUI,  Flutter and standard Swift with SpriteKit.  

The app I'm building is an update of my Brainiversity brain training game. Brainiversity has a number of small games that test your math, memory and word skills. I've been making versions of this app since 2007, so I have code bases written in C++, ActionScript and Lua. I used the existing "Add It Up" mini-game for my vertical slice.

Swift and SpriteKit

Line count: 647
SpriteKit version

This version is very similar to the original C++, ActionScript and Lua versions. It uses sprite animations to give the game zing, and everything is imperative - so the text in the answer counter label in the top left of the screen is manually updated when a new question is generated. 

I found SKAction  was useful in handling animations. This made it really easy to chain together a sequence of events like:
  1. a cross appears when the user presses the wrong answer button,
  2. the correct answer scrolls in from the right of the screen,
  3. after a pause, answer counter pulses as it counts up one,
  4. the answer scrolls off screen to the left as a new question scrolls in from the right
  5. the buttons flop over to reveal new answer values.
Compared to the SwiftUI and Flutter versions, there was a lot of code to make stuff happen, and to be honest, after making apps with reactive UI, programming this way felt old fashioned.

SwiftUI

Line count: 210
SwiftUI version

I've already made a few apps in SwiftUI so I was used to the reactive paradigm. Reactive programming results in reduced code which makes reading the code so much easier. I love how SwiftUI handle state with the @State property wrapper - it seems a lot cleaner and less code than Flutter's SetState or Provider solutions.

The use of VStack, HStack and Spacer makes it really easy to lay out the screen. Here is the code to layout the question and the answer buttons.

   VStack {

      VStack {

        HStack {

          Text("Correct: \(correct)")

            .bold()

            .font(.system(size: width * 0.20))

          Spacer()

          Text("Wrong: \(mistakes)")

            .bold()

            .font(.system(size: width * 0.20))

        }.padding()

        Text("Select the correct answer for the math equation below from the multiple choice buttons.")

          .font(.system(size: width * 0.20))

          .padding()

        Text(question)

          .font(.system(size: width * 0.35))

        VStack {

          HStack {

            Spacer()

            RoundButton(title: "\(answer1)", color: Color.red, size: width, function: {tryAnswer(button: 1)})

            

            Spacer()

            RoundButton(title: "\(answer2)", color: Color.orange, size: width, function: {tryAnswer(button: 2)})

            

            Spacer()

          }.padding()

          

          HStack {

            Spacer()

            RoundButton(title: "\(answer3)", color: Color.green, size: width, function: {tryAnswer(button: 3)})

            

            Spacer()

            RoundButton(title: "\(answer4)", color: Color.blue, size: width, function: {tryAnswer(button: 4)})

            

            Spacer()

          }.padding()

        }

      }

      Spacer()

    }

    .navigationTitle("Add It Up")

    .onAppear {

      generateResults()

      width = UIScreen.main.bounds.width * 0.3

    }


This is fairly similar to Flutter, which uses Columns, Rows and Spacer - here is the button section code in Flutter:

return Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
answerButtonRound(
answer: answerList[0],
color: Colors.green,
size: buttonSize,
func: () => {_answerButtonPressed(buttonNr: 1)}),
answerButtonRound(
answer: answerList[1],
color: Colors.blue,
size: buttonSize,
func: () => {_answerButtonPressed(buttonNr: 2)}),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
answerButtonRound(
answer: answerList[2],
color: Colors.red,
size: buttonSize,
func: () => {_answerButtonPressed(buttonNr: 2)}),
answerButtonRound(
answer: answerList[3],
color: Colors.orange,
size: buttonSize,
func: () => {_answerButtonPressed(buttonNr: 4)}),
],
),
],
);

Swift code is definitely a lot cleaner to read with less nesting and less boiler plate. The child and children parameters of Flutter take up extra space and cause more visual clutter.

I hit a brick wall with SwiftUI when I wanted to chain animations together with some state updates in the midst of all the action. I could not find a way to make the question label animate away, then update the state for new questions, then slide an updated question text back on screen. The best answer I could find was to start the slide out animation with a slide in animaion, then set a timer to call my generateNewQuestions() function so it occurred halfway between the slide in and out.

Maybe I didn't look hard enough for the right way to do this, but that's currently an issue with SwiftUI documentation. There's not much of it out there. Whereas I found multiple examples and tutorials on how to do what I wanted in Flutter on flutter.dev and other web sites.

Swift Pros

  • Light weight code that is easy to read. You can do a lot with so little.
  • Dark theme just works out of the box.
  • I can target Apple Watch.
  • CoreData is nice and works out of the box with Apple devices.
  • The state system is really easy to use.
  • No semi-colons!

Swift Cons

  • App Preview is slow to update, even on my M1 MacBook Air - and I constantly had to keep hitting Resume to rebuild the preview.
  • Documentation is lacking, especially compared to Flutter. Thank goodness for Hacking With Swift - the best resource for Swift developers.
  • Can only make apps for the Apple ecosystem.
  • Refactoring is less advanced than Flutter.

Flutter

Line count: 304
Flutter version


Even though Flutter has sightly more boilerplate code to set things up, I like how everything is a widget and it's pretty consistent. You generally nest widgets within widgets - and when you go too deep you refactor out into new widgets which makes for easier to read code. SwiftUI has nesting as well, but also has modifiers which I'm not 100% sold on.

In SwiftUI to make the text bold you add a .bold() modifier.

          Text("Wrong: \(mistakes)")

            .bold()


In Flutter you add the bold as part of a parameter of Text.

                        Text('Wrong $mistakes', style: TextStyle(fontWeight: FontWeight.bold)),

I guess what feels weird with SwiftUI modifiers is that to give a screen a title, you add the modifier at the bottom of the view - so when you read the code you aren't seeing the layout as it occurs. Whereas with Flutter, you add the screen title at the top so you read the screen in the order it's drawn. Maybe I'm being picky, but I found that a little weird.

Even though Flutter is a bit more wordy, I found it a lot easier to find out what modifiers are available by simply pressing CTRL-SPACE in VSCode. Maybe there is an easy way to find out what  modifiers are available for Text() in Xcode apart from going into the Library Panel and searching (which is a pain) - but I have yet to find it.

Another plus with Flutter is that it's so easy to refactor code. Are your widgets nested too deep? Turn them into a new reusable widget by hitting Refactor and choosing Extract to widget. Want to wrap everything in a new Row? Hit Refactor and choose Wrap with row. Want to get rid of a top level widget? Again, hit Refactor and choose Remove this widget.

Xcode has a refactor option, but doesn't offer as many features. 

In terms of Dart vs. Swift - I have to admit I found them fairly interchangeable and could happily switch between the two. Most of the stuff I am using to build my apps is common across both. All the modern language features like helper functions for lists such as sort, insert, and index functions were common to both and in many cases had the same name.

Flutter Pros

  • Hot reload is amazing. Instant updates on my actual target device makes development so much faster.
  • Great documentation. Not only is the documentation at Fluter.dev awesome, but there is a dedicated YouTube channel with lots of content including the useful Widget of the Week.
  • Lots of great packages at Pub.dev. The odds are, if you need something, there is a package already available. Want to add charting to your app? There's are many packages for that.
  • There is a Widget for literally everything. 
  • Refactoring with VSCode is super easy.
  • Supports a lot more legacy devices and older OS versions.
  • Can make apps for iOS, Android, Mac, Windows and web. My website, www.redspritestudios.com is written in Flutter :-)
  • Flutter is open source. So you can drill down into any piece of code to see how it works. There is no blackbox like Swift.

Flutter Cons

  • Can't build for Apple Watch :-(
  • 2D only. So no chance of doing any activities in 3D.
  • Slightly more verbose compared to SwiftUI.
  • State management is not as clear cut as SwiftUI.
  • I have to type a semi-colon at the end of every line.

Conclusion

I love SwiftUI and have already published apps built with SwiftUI. 

But, for my new app, Flutter has the edge. It has lots of widgets, a large amount of good quality documentation, cross-platform support, and an animation system that does what I need.

More importantly I actually found it a tad faster to build my vertical slice in Flutter. This was probably due to the abundance of quality documentation helping me solve roadblocks quickly, and having a faster feedback loop with hot-reloading.

I plan to get an MVP of the new Brainiversity up as soon as I can, and I will build out the rest of the activities with feedback from users. I'll post again when it's ready to play.

Let me know if I got anything wrong, or if there is a better way of doing things.

Cheers,
John


Monday, August 26, 2019

Third In The Space Watch Trilogy

WatchOS 6 is launching soon, and I've been busy preparing some new games exclusively for the Apple Watch.

I've already released Kepler Attack, a fast paced space shooter inspired by the arcade classic Gyruss, and I've recently completed Star Warp, which is now available for pre-order on the App Store. Star Warp will launch on the 4th of September and is inspired by Galaxians.

And right now I'm busy working on another space game -  the third in my Space Watch Trilogy - and that game is called Asteroid Commando. No prizes for guessing the inspiration for this one...


Like the other two games, Asteroid Commando is built using Swift 5 and SpriteKit and is designed to take advantage of all the latest features of the Apple Watch. It uses the Digital Crown with haptic feedback, runs at a silky smooth 60fps, works with Game Center for the Watch and runs independently of the iPhone.

I've built up a framework while developing Snappy Word, Kepler Attack and Star Warp - sharing a menu system, leaderboard and save/load system between games lets me kick off new projects and get into the core game a lot faster.

Initial sprite set for the game
I'm finding the constraints of the Apple Watch a joy to work with. The smaller screen size and limited input, coupled with the shorter play sessions means that a Watch game is much smaller in scope than the average mobile game. And this means shorter development times without compromising the quality of the experience. In some ways, the Watch is a great delivery platform for what is essentially paid hyper casual games.

I plan on doing more regular updates as I close out Asteroid Commando, so please check back to see the new features I'll be adding over the coming weeks.

Cheers,
Johnno


Friday, August 16, 2019

Space Watch Trilogy

It's been almost 3 months since Kepler Attack launched on the App Store as a paid Apple Watch exclusive.

The game did well out of the gate, getting a bunch of downloads without any featuring and has continued to perform well. So far it has garnered over 61 rating with an average review score of 4.6.

I quickly followed up the launch with an update that included iOS support - letting folks play the game on their iPhone or iPad using the touch screen in lieu of the Apple Watch Crown.

In terms of marketing I managed to get only two online reviews despite sending the game out to as many Apple and Watch sites as I could. I'd like to give a big shout out to The Apple Watch Cast and HotshotTek for their support! I will continue to try and get the other sites to notice my game, so if you're reading this you haven't heard the last of Kepler Attack!

As far as I can tell, most of my installs have been organic via people finding the game on the App Store through search and browsing. 

However, just this week I was excited to see that Apple featured Kepler Attack in the What We're Playing section of the App Store!

Featured on the App Store!

Plus, Kepler Attack is also featured on the Apple Watch App Store running on WatchOS 6 Beta!

The new Apple Watch App Store

Before any of this happened, I had decided to dig in and go hard on Apple Watch games. And now with the featuring it feels like I may have made the right call - of course time will tell.

It's no secret that I am a huge Apple Watch fan, having worn an Apple Watch since the day they were first released. I even had a game (Snappy Word) on the Watch on launch day. 

I love my Watch and I love games and I think there are others like me out there who enjoy playing on their Watch. The only problem is it's been damn hard to find apps and games made for the Watch. I'm hoping that the upcoming Watch App Store changes that.

So, along with Kepler Attack, I've been working hard to make a number of games for people to play now that they will be able to browse for content on their Watch.

I figured that I would share my journey making these games in a series of dev blogs.

To kick this off, here's a look at my next Watch game called Star Warp. It's another space shooter game, this time inspired by Galaxian.


Star Warp builds on a lot of the work I did for Kepler Attack - using the same framework for high scores leaderboards, front end menus, game over logic and ship movement.

I'm hoping to use the work I've done to start to evolve each game. I don't necessarily want to make them more complicated as I think there's a sweet spot for content and play session time for these games - but I definitely want to start pushing what the Watch can do in terms of mechanics and play style.

I'm aiming to launch Star Warp in early September - so In the meantime, why don't you check out Kepler Attack on the App Store here!

Oh, and the title of this post is Space Watch Trilogy... so yeah, there is a third space game in development.. but that will have to wait until the next post!

Cheers,
Johnno

Wednesday, May 22, 2019

Making Kepler Attack for Apple Watch



Kepler Attack is a retro space shooter that I made exclusively for the Apple Watch.

If you have an Apple Watch then you can get it here from the App Store.

Kepler Attack Game Footage

Why Apple Watch?

As my friends know, I am a huge Apple Watch fan. I've had a Watch since day one and I've made a number of games for the platform. All of these games are simple puzzle games - not the sort of games you would use to show off your Apple Watch to your friends.

So I figured it was about time the Watch had such a game!

And this, dear reader,  is why I created Kepler Attack.

Have I succeeded in creating a killer Watch game? Time will tell, but I think I've done a pretty good job in making something I can be proud of.

Origins

I started Kepler Attack on the 15th October 2018 and used art assets from my Ultra Dash game. The Watch app was part of the Ultra Dash project and my initial plan was to mimic that games mechanic, which involved racing through space avoiding obstacles.

You can read about the making of Ultra Dash here.

Months earlier, a friend and I had discussed Gyruss and how it would be perfect for the Watch. As I began to build out this new game I subconsciously leaned into Gyruss' mechanic. When I showed him Kepler Attack months later he exclaimed "Hey, I told you that would be a great game for the Watch!". So thanks Iain!

Controls

I explored a number of ways to control the player ship. I tried tapping the screen to move the ship left and right but this didn't work. It was slow and your finger obscured the action. Buttons weren't viable as the screen was too small to accommodate them.

As soon as I added the Digital Crown controls it was obvious that this was the right choice. Using the Crown as the controller led to the next logical change - making the the ship move in a circular motion, not just left and right.

On the 4th of November I split out the Watch game to be its own project, removing it from Ultra Dash.

Art

For Ultra Dash I wanted to make the art myself. In my making of blog post for that game I wrote:
One of my hopes for Ultra Dash is that it has the chance to find an audience. I am a bit worried that the art may impact on that chance. Anecdotally any screen shot of Ultra Dash I tweeted would get around 0 favourites while a beautiful 3D Billy Carts screen shots could get up to 20 favourites. People like beautiful games.
This isn't a surprising revelation, but it's easy for people to forget this simple fact. 
Well, I was right. People do like beautiful games. And my art was programmer art. But hey, I got to do the art for the game - even if it didn't set the world on fire.

So for Kepler I listened to the feedback and contacted my good friend and amazing artist Pete Mullins to replace my placeholder art with something good.

Space Ship Design

I created the placeholder art in Affinity Designer and played with their sizes to get the hero and enemy ships to look good on the small Watch screen before getting Pete to redo it. This way I could make sure I had the required number of ships and their sizes locked down.
My placeholder ship art


Pete and I discussed how the final ships should look. I gathered a bunch of reference material for old vector style graphics from the likes of Asteroid and Tempest, as well as the blocky sprite stylings of arcade shooters.
Final art inspired by classic eighties arcade space shooters

The old school pixel look won out and Pete began creating some cool looking ship designs.

As well as the ships, we updated the asteroids, power ups and projectiles. We also added a new blocky pixel inspired font. The game was playing really well with super smooth controls and it looked the part.
Programmer Art

Final Art by Pete Mullins

Logo Design

I wanted the logo to capture the spirit of the classic eighties games like Galaxian and Galaga.
Classic arcade game logos


I mocked up the first attempt at a logo which served well as a placeholder piece.
My initial attempts at a logo


The final logo designed by Pete managed to capture the eighties arcade vibe while still feeling fresh. Importantly it also looked great on the small Watch face.


The final logo by Pete Mullins


Coding

I built the game with Xcode 10 using Swift 5 and the SpriteKit framework.

I used a storyboard to lay out the main menu in Xcode. Creating UI for the Watch is surprisingly easy using a combination of vertical and horizontal groups that can be stacked. I only used one screen with the menu and game screen sharing this space. The game screen (a SpriteKit Scene) is initially hidden from view.

Xcode menu storyboard
When the player taps to start playing I hide the menu group and show the SpriteKit Scene. This made it easier to transition to the game scene from the menu and not inherit all of the Watch UI that would have appeared, like the back button.

I laid out the game scene in the Sprite Kit Scene editor.
The scene editor for the game screen
I placed the hero ship and score and UI labels here, and programatically generated the enemies and asteroids.

Enemies

I used a lot of built in features of Xcode and Swift to make the game. Xcode has a simple particle emitter editor so I created the star field with this. The stars are an emitter at the centre of screen that spawns various sized blue squares that shoot off in different directions at different speeds.

For the enemy attack patterns I used Swift's bezier path function. With this I simply had to pick a number of random points on screen and plot a bezier curve through them. Super easy and it looks great!

        // create a bezier path that defines our curve
        let path = UIBezierPath()

        // Start position
        path.move(to: startPosList.randomElement()!)
        path.addQuadCurve(to: arcPosList.randomElement()!,
                          controlPoint: arcPosList.randomElement()!)

Then I attached the paths to the enemy ships and started them on their merry way.

            enemy.sprite.run( SKAction.repeatForever(
                SKAction.sequence([
                    SKAction.wait(forDuration: duration),
                    SKAction.follow(path.cgPath,
                                    asOffset: false,
                                    orientToPath: true,
                                    speed: 150.0)
                    ])),
                       withKey: "path"
            )

SpriteKit actions are a really powerful part of SpriteKit. As you can see above, you can run a set of actions on your sprite. There are a whole bunch of useful action methods that when chained together create some pretty cool movement sequences.

Actions let you follow paths, fade, scale your sprite on the x and y axis, wait for set time durations, move the sprite set amounts or to specific locations - you can add these inside fixed, single and repeating loops - and you can also call your own functions from within.

The majority of the hero, enemy and obstacle sprite logic was built with SKActions.

User Testing

Once I had a playable build I used TestFlight and the public beta link system to open up the game to external testers. I did a call out on my social media and posted on the TouchArcade forums. From these two sources I got a reasonably sized testing group to get some good feedback.

I would make changes and push out new builds, polishing the game until I was happy.

At the end of March 2019, I submitted Kepler Attack to the App Store as a pre-order and set the release date for 6 weeks in the future. Now it was time to get the word out...

Pricing

I set the price to 99c (Tier 1). I toyed with a higher price point but wanted to capture the arcade feel that inspired the game, and 99c felt like the right amount to charge for it.

Going free to play was out of the question as there is no way to serve ads or offer IAP on the Watch. Will users pay 99c for a game any more? I'll soon find out...

Marketing

Analysts calculated that there were around 45 million Apple Watches shipped in 2018. The Watch isn't the most obvious gaming platform, but I believe that a small percentage of owners would surely be interested in playing a game on their wrist. And even a small percentage of 45 million is quite a large number of potential players for an indie game developer!

My biggest challenge will be reaching those users, but I have a number of ideas on how to do this and will try a mixture of paid ads and boosted promotions on sites like Facebook and Instagram.

The Future

Right now I'm focused on getting the word out to those people who own Apple Watches. As mentioned above, they are a tough market to connect with. I'm hoping that if they can be made aware of my little game then they may want to buy it. It is the perfect game to idle away the time between meetings and waiting in line.

I have an update ready to release within a few weeks of initial launch. This new update adds a Top 100 leaderboard which is accessible right on the Watch. This is a really fun feature and adds a lot to the game.

My fingers are crossed that it does find an audience, but whatever the outcome, I can honestly say that I've made one of the best Apple Watch games you can play.

And I had fun doing it!

- Johnno

Development Environment

IDE: Xcode 10
Language: Swift 5 with SpriteKit

Tools

Programmer Art - placeholder art was made with Affinity Designer
Final Art - produced by Pete Mullins using Photo Shop
Icon Creator - Asset Catalog Creator
Screen Shots - Screenshot Creator Pro

Version Control - Source Tree and Bitbucket
Tasks - Trello to keep a list of To Do, Doing and Done tasks as well as backlog for future updates

Design and Code: John Passfield
Art: Pete Mullins



Friday, April 27, 2018

Working on Multiple Projects


One of the things I struggle with is working on multiple projects at the same time.

Fixating on one project and wanting to see it through until the end before moving on to the next one is something I tend to do. This may be a great approach for some, but for me, I need to share my time between multiple things.

As a long time developer I’ve managed to build up a back catalog of games and apps - and a number of these require maintenance to stay up to date.

As well as updating older games I’m always working on new stuff - be it prototypes or new games that I plan to ship.

And on top of that, I’ve been trying to blog more often than I have been. In fact, just writing this blog post was a challenge as I felt that I needed to focus my time on the programming tasks I have at hand.

So I did some research into techniques to help manage working on multiple projects at the same time and I thought I’d share these with you. As for the effectiveness of these techniques, well, we’ll have to wait and see. This might be the subject of a future blog post!

But first, here’s my current strategy for managing multiple projects, which admittedly, while not perfect is better than nothing.

What I Currently Do

Trello

I use Trello to keep track of all my projects. I have a board for each individual project with the following lists: Backlog, To Do, Doing and Done

When I have a new idea for a feature I place it in the Backlog list. I regularly evaluate this list and move what I should be working on next into the To do list. When I need a task to do I will move it from the To do list into the Doing list. When I complete a task I move it into the Done list. 

I find this really helpful when I have a half hour to spare and want to get something done. I  simply pull up my list and pick a task - I don’t have to think as I’ve already planned out the work.

Trello for Snappy Word

I use Trello on my computer and my iPhone.

Trello on mobile is invaluable for adding tasks to my backlog while I’m out and about.

Notes (on iOS)

I use Notes on iOS to quickly jot down ideas. These can be a single line to a few paragraphs. I sometimes do a quick sketch on a post it note and insert that into my note or use the drawing feature to add a quick sketch.

I have a Game Ideas and App Ideas folder that I throw stuff into. 

These aren’t related to any specific project I’m working on, but are reserved future distractions :-) If I have an idea for an existing project, I do this in Trello. Keeping the new ideas in notes helps separate (mentally and physically) the possibilities from the practicalities.

Every so often I review the ideas and sort them based on what I want to do next after my current project have been completed. 

It’s always a good sign if that "amazing game" you wanted to make is still an amazing idea six months later. More often then not I think to myself “That’s not such a great idea…” But still, I believe it’s really important to record these thoughts as there may be a germ of a great idea in there somewhere.

Example game idea note


Google Docs

As well as Trello I use Google Docs to track my day to day work. I have a Work Log document that I write down what task I’m working on, any notes about that task and other relevant information for the day. I prefix each task with the project name. These notes are useful as they record any extra information that the initial Trello To do item may not have had.


Here’s an example entry from when I updated Ultra Dash:

Sunday, 31st December 2017 
DASH: Update the background sizes for iPhoneX

I collate these notes and use them when I check in my project to source control (I use Sourcetree and BitBucket).

I’ll often go back over my notes to work out how much time I’ve spent on a particular project. The Trello tasks are what I planned to do and my Work Log is what I actually did with more details than the initial Trello task description. 

The Work Log also includes other notes such as when I submitted a build to the App Store or when I updated the latest version of Unity, etc. It’s essentially my timeline of all my projects.

It’s also great for those times when I feel like I’ve accomplished little, but on reading over my notes I can see reasons why (being sick, on holidays) or actually see that I did do a lot but it’s all behind the scenes and not reflective in the latest build (refactoring code, updating ad providers).

My Challenge

So I have a system that works for me in terms of organising and tracking my projects but my biggest issue is task switching. How can I effectively parcel out my time between projects and actually switch between them?

A solution

It seems obvious now as I write this, but the big takeaway from my research is that I need to create a meta to-do list with tasks from each project interweaved so that when I complete a task from Project A I can move on to the next task which could be from Project C.

One caveat is that task switching can take a toll when switching context - which often happens when switching between two very different projects. To minimise this it's suggested to try grouping similar tasks together.

From what I’ve read, it’s also beneficial to try and limit the tasks times to around 20-30 minutes each, which thankfully is something I already do. 

Obviously there are systems in games that can take weeks to complete, so the trick here is to be able to break these systems down into manageable small tasks. This fits well with what I do with my Trello board and the Backlog list.

Trying it out

I’m going to give this a go and see if it helps fix my problem of staying on one project for too long at the expense of others. I'll add a future task to write an blog post on the results :-)

So, what techniques do you use? 

Let me know as I would love to try them out and see if I can improve my productivity!

- Johnno

References