3
\$\begingroup\$

I'm a fellow game programmer who's done many game engines in Game Maker 8.1, Visual Studio XNA and MonoGame with C#, and one in Java Android with Eclipse. I'm very used to C# and love it plus the VS environment.

Now I'm trying to develop games for the App Store for iPhone and iPad (using Xcode 7 with a Macbook running Yosemite 10.10.5). I don't yet have an actual iPhone to test with, but the simulator is working with the blank and example projects I've found.

By way of googling, this is what I've looked at so far:

http://codewithchris.com/xcode-tutorial/

http://www.raywenderlich.com/40293/learn-to-code-ios-apps-2-strings-arrays-objects-and-classes

There was also a Storyboard example which I did not like. My intuition is to not use a wizard for anything, and the Storyboard builder seemed a lot like Windows Forms when I can just use the XNA draw functions.

Neither of those tutorials was very helpful and now I'm paranoid that I'm on the wrong track. Now I'm asking myself questions like should I be using SpriteKit or SceneKit? Should I be using Swift insteada Objective-C?

The thing is, if I can figure out how to draw pictures in a game loop, then I think I'm all set. However, I think I understand that I'm gonna need at least one UIView or Scene. What I want is a master_draw() function that gets called 30 times per second in main.m, and in master_draw() I loop through all objects and call their individual draw functions. Same thing with a master_update() function.

And I also found this open source example: https://www.cocoacontrols.com/controls/1w-flappy

That example...I thought it would be the most helpful of all. But I couldn't find any game loop in it at all.

Am I on the right track? Does iOS stuff work totally different than a traditional game loop?

Specifically, I have 2 major questions:

  • What new project type should I chose? Blank, Single-View, or Game?

  • How to set up a game loop? (if possible)

What I'm thinking is something like this:

void master_update() // typically called 30 or 60 times per second
{
  foreach (GameObj G in ListOfGameObj)
    G.update(); // update all objects in the list of objects
}

and of course...

void master_draw() // typically called 30 or 60 times per second
{
  foreach (GameObj G in ListOfGameObj)
    G.draw(); // draw all objects in the list of objects
}

Where do I add that code and where do I call it? Is something like this possible in iOS or am i gonna hafta use a completely different architecture?

P.S. The kind of game I'm doing is a simple 2D puzzle where you hafta match up blocks. Nothing too fancy.

\$\endgroup\$
  • \$\begingroup\$ Use Storyboards - they are not wizards nor are they code generators. They are the preferred screen-layout tools, but there will always be cases where it makes sense to do certain things procedurally. \$\endgroup\$ – Steve Ives Feb 25 '16 at 15:39
2
\$\begingroup\$

For a 2D puzzle game for iPhone and iPad, SpriteKit would be the easiest way to do this. SpriteKit is made especially for developing 2D games. You don't have to bother creating a scene graph, how to draw images to the screen or how to create a game loop. It is already there, ready for you to use it.

Start with creating a new project from the Game template and choose SpriteKit. This will already provide you with a basic scene and handlers to create spinning space ships when tapping on the screen. (Just test it by running the game.)

Drawing an image is as easy as creating an SKSpriteNode object, setting its position and adding it as a child to the scene or some other node in the scene graph. E.g.

let pieceOfThePuzzle = SKSpriteNode(imageNamed: "puzzle")
pieceOfThePuzzle.position = CGPoint(x: 100, y: 200)
node.addChild(pieceOfThePuzzle)

would add the pieceOfThePuzzle to the node node at position (100, 200) and it will be automatically drawn in the next frame. SpriteKit will automatically find and load the correct image for you.

Also, there will already be an update method that is run before drawing the next frame. This should be enough for you to get started.

As for Swift vs. Objective-C: If you already have a preference for one of the languages, use that. If not, use Swift. Swift is newer, easier to learn and more powerful in my opinion.

\$\endgroup\$
1
\$\begingroup\$

1- Well, I have not a huge experience in IOS native development. But if you want it in environment like other Game Engines then I would recommend you to use SpriteKit. You can get start from this tutorial.

2- If you want to set Game Loop in normal Objective-C environment, you can set NSTimer with custom frequency like,

NSTimer myTimer =[NSTimer scheduledTimerWithTimeInterval:0.03
    target:self
    selector:@selector(gameLoop)
    userInfo:nil
    repeats:YES];

-(void)gameLoop{}

And it is a good practice to Deactivate this timer when you get done with this, by,

[myTimer invalidate];
myTimer = nil;
\$\endgroup\$
0
\$\begingroup\$

+1 for the answers so far, but I just don't like SpriteKit. I don't understand sprites that are apparently also objects and worse, are automatically drawn somehow. I need to see code. I need to see code that I actually wrote, or at least actually called the library function. Otherwise I feel like I don't have complete control over what is being drawn, when it's changed, when the object disappears even tho the object may not have been destroyed, etc. As a rule of thumb, a fully functional language such as Swift can do this without having to learn another language within a language (wizard or SpriteKit UI or something), and it's the way I've been programming for years.

Therefore I decided to answer my own question in the hopes that other programmers similar to me will get off to the right start.

Who am I? A C# programmer who's made many games/apps/simulations in XNA and MonoGame using Visual Studio. Up until a few days ago, I had never touched a Mac or iOS languages. I love C# and thought iOS programming in Objective-C would be similar. Boy was I wrong. And regarding other options, why use SpriteKit or SceneKit when you can just use the native draw functions? (called Quartz I believe, but that threw me off. Quartz is just the native Swift drawing library as far as I can tell.) That would be like learning another language within a language when you're already trying to learn Objective-C or Swift.

If that's who you are, then this answer is for you:

Use this tutorial to setup your new iOS game and learn how to draw. In particular, you want a "Single View App" (not "Game"!). The tutorial makes a new class called Draw2D that has the main drawing function. It shows how to draw primitives such as lines, and at the end it shows you how to draw pictures. Violla! No SpriteKit wizards necessary that you have no idea about anyway! Pretend the Draw2D class is your "main" class and put your main variables and object lists/arrays in there. This will make it very easy to reference all objects, which are created and stored in arrays or lists.

Absolutely use the Swift language! Do not use Objective-C! (This will force you to target iOS versions no earlier than 7, but that's definitely old enough to let a lot of phones run your game). Swift is native iOS code and similar to C# but with different arrangements in the syntax. Objective-C is basically stone-age C hacked to unreadable dangers. Just from looking at it, I'm pretty sure you can blow your own legs off by going out-of-bounds during file writes or array traverses...just like plain C. Yes this is my opinion, but if you're reading this answer, you're hopefully like me.

Learn what ! and ? do. Not even I am 100% sure yet, but basically, Swift does not allow objects to be null (nil) by default---unless you explicitly say they can with a '?' at the end of the variable name at instance declaration. Same thing with functions returning an object. Use '!' to force the language to not do any safe nil checking when accessing the object. For some reason the compiler is gonna require this on certain accesses to your object. Just be safe and always manually do if (MyObj != nil) first.

You need to set up a NSTimer to automatically call your draw function every x seconds. This is very important! Don't skip this huge paragraph! Find the code here or just copy this: var timer = NSTimer.scheduledTimerWithTimeInterval(0.033, target: self, selector: "draw_now", userInfo: nil, repeats: true). Make sure the timer is a part of Draw2D. See here's the thing. For some reason, the custom UIView we created in the tutorial only gets called once or twice at the beginning, so we need a timer to call it again and again. I wanted 30 fps so I used 0.033 for the interval (so it will get called once every 0.033 seconds). But there's a trick to this. The timer needs to call a selector; it's the string parameter. But don't make this your default drawRect() function! Instead, make a new function called draw_now() like I did, so the NSTimer parameter should be "draw_now", no parentheses, and in draw_now() (a function of Draw2D) put this sole line of code: [setNeedsDisplay()]. Type that exactly, including the brackets. That's the trick! That code somehow forces the UIView to redraw itself by calling the drawRect() function. I have no idea why, but if you set up your timer to call drawRect() like I mistakenly did at first, it just doesn't work. drawRect() gets called again and again, and you can check that in the debugger, but things just don't get drawn for mysterious reasons having to do with bizarre and ungainly things called contexts. Anyway, you have to call a function with a single line of code: [setNeedsDisplay()]. And that code goes and does magical things to make the system call drawRect() with the right context. Many thanks to stackoverflow at this link for that code.

In my main draw function (drawRect()), the first thing I did was call master_update(), which is my own function I made. It basically loops through all the arrays of objects and calls their individual update functions. The point is, with this setup, the timer effectively runs the update loop and the draw loop, which are therefore in sync. I always want in-sync updates and draws in my games, though you may want it differently. Personally I've never found a reason to use variable draw rates, and keeping it in sync makes things so much simpler.

Access the touch functions so you can control what happens when a user touches the screen. Go to this youtube video and jump to 2:40, where he begins overriding the touchesBegan function. Make sure this overridden func is in your Draw2D class.

Each class needs its own constructor, and Swift is picky about it. I had trouble with this because Swift allows many weird types, such as required, convenience, delegate, and others. The one foolproof constructor I found was required init?(parameter1: parametertype1, parameter2: parametertype2, etc). All my classes used this as the one and only constructor that the compiler did not complain about. Even Draw2D had this same single constructor, but it needed a weird parameter: required init?(coder aDecoder: NSCoder). Not sure what that was all about. However, your constructor may need to call super.init() at the end, which may have its own parameters too. I think the super thing is for subclasses that inherit parent classes, so you have to call the parent's constructor too. This is apparently necessary before using self (which would be this in C#) in your constructor.

Go here and learn about drawing points. Not pixels. Points. They are different things in the Mac world. This is not how we do it on desktop PCs, but so far I haven't had much trouble. Apparently it's pretty useful to draw consistently to different devices with different screen resolutions. It gave me a fairly straightforward way to just scale everything to fit the screen, which is the quick and dirty way I wanted to support multiple devices for my first iOS game. By the way, you can do this with var screen_width = UIScreen.mainScreen().fixedCoordinateSpace.bounds.width, which gives you the width of the actual screen in points. (Unfortunately, this will force you to target iOS 8 and above, which means less iPhones will support your app. I have not yet found a different way to do this while staying compatible with iOS 7. But according to this, it's not much to worry about.) Then if you want a 20x12 grid, each square will be screen_width/20.

Now you are finally ready to program 99% the same way you did in XNA and MonoGame! All your objects have their own update() and draw() functions, and in the main update you just iterate through each object in your array and call MyObj.update(); Same thing with the draw.

Keep in mind I'm using a Mac Book running Yosemite 10.10.5 on Xcode 7 with the Swift Language. Who knows what could happen, if anything, on later versions.

\$\endgroup\$
  • \$\begingroup\$ Just one question... You say you've made many games/apps with Xna and MonoGame. And I take it you've done that, because you've found the framework a joy to work with. In that case, why not also use it for this iOS project? You do know MonoGame runs on iOS, right? ;) \$\endgroup\$ – Falgantil Dec 18 '15 at 10:46
  • \$\begingroup\$ @BjarkeSøgaard with Xamarin, yes. Otherwise I don't know how. Xamarin is a paid product with a very limited free trial version. Even if I had the money, my first suspicion would be how fast is it, since it isn't native code. \$\endgroup\$ – DrZ214 Dec 18 '15 at 21:30
  • \$\begingroup\$ Actually if you studied it a bit, you'd find out that it is in fact native code. Sure, it's written in C#, but it's being compiled to native byte code. So two examples, one in c# and another in obj-C, doing the exact same thing, should also show the exact same performance. Although in reality it might differ a bit, since you can't know if what Xamarin translates your c# code to, is the same that xcode translates obj-C code. \$\endgroup\$ – Falgantil Dec 19 '15 at 2:16
  • \$\begingroup\$ @BjarkeSøgaard In my opinion, the best way for these sort of things is if it translates to an actual iOS project in Swift (or Obj-C if you really really want). Then you can open that project and tweak it before compiling into the actual app. Of course this will require an actual Mac and Xcode, which perhaps defeats the purpose of using C# and VS in the first place...but if you can afford Xamarin, then presumably you can afford a Mac as well. \$\endgroup\$ – DrZ214 Dec 19 '15 at 12:50
  • \$\begingroup\$ Yeah you'll still need an actual Mac, even with Xamarin. Of course with proper dependency injection, you can do all the testing on the PC, in a DirectX game, and then switch out the few implementations on iPhone, such as the Touch handling. And by debugging on PC, you get a lot of extra debugging features, that you wouldn't have in a IOS project. But if you prefer using obj-C or swift over C# for iOS, then I wont stop you :) \$\endgroup\$ – Falgantil Dec 19 '15 at 17:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.