Showing posts with label Objective-C. Show all posts
Showing posts with label Objective-C. Show all posts

Friday, 13 February 2009

Tetris : the implementation of a classical game in Objective-C/Cocoa

First of all the source code of the game can be found here. Background for the game can be found on wikipedia.

This implementation is a first attempt to implement it, in this version I was more intrested to get it to work than in the nice graphical aspects.
As you can see in the picture , it surely won't win a prize as the most sexy application :-).



This game again is an implementation of the classical MVC design pattern, with the difference that their are 2 views.

The model is a TetrisBoard (subclass of Board) on which you can move a piece (the so-called Tetrominoe (superclass of a set of pieces)).
The tetrominoe is the abstract superclass of all the tetrominoe's. It's very handy to model the pieces as a class, later on I can add things like a skin, or a another way of rotating. 

There are 2 views, the TetrisView and the TetrominoeView. The first one is the graphical representation of the  TetrisBoard; the second shows the next tetrominoe.

The model and the view(s) are connected via the TetrisController.

Saturday, 7 February 2009

Frameworks

While I was busy writing Tetris (for Mac using Cocoa of course), I was also wondering how I could create a simple framework of my generic classes I wrote for the Game of Life.

In the Apple documentation they are referring to 2 types of frameworks, public ones and private ones.
The public ones you find in /System/Library/Frameworks and /Library/Frameworks.
Now for me, its not a good idea to put my frameworks in a public place, so thats why I opt to create a private framework in my own location (later on its a bit more difficult to use it , but at least I have full control over it).

The first thing we have to do is to startup XCode , and select File>New Project. In the popup that follows you select 'Cocoa Framework'



And click the 'next' button, you now get the opportunity to give a name to your framework.

In a next step, you'll add files, debug them etc etc (the usual development so to speak).
At some time you'll be ready for releasing the framework you made.

Of course , if you want to use your framework in other development projects you need to 'publish' your .h files (your header files).

And this you do in the project browser :



As you notice in the picture, you select in the project explorer 'Targets/name of your framework/Copy headers' . On the right handside you see all your .h files.
The second column says 'Role', now file by file you can change the role (you do this by clicking on the small triangle, you then get a popup with 3 choices).

Its important to change the ones you want to be public , by default they are all 'project'.

A last step is to build the framework and save it some where. A good convention is to save all your frameworks in a location called 'frameworks' (just like Apple does).
Changing the location you do in the project settings (XCode>Project>Edit Proj
ect Settings).



And now you build it and voila you have a framework.

Tuesday, 20 January 2009

The Matrix

I do not understand why Apple (or NeXt) didn't include a Matrix class in their foundation classes.
In gaming applications it would be very handy to have a 2-dimensional (or 3-dimensional) data structure.

Of course when I talk about a Matrix I don't mean the mathematical variant, therefore you can find much more performant implementations; but for the more common things like cell's on a board, I made my own Matrix class.

This first version is a very simple one, the underlying idea is to have an array of arrays. So a NxM matrix is implemented as a an array with N elements where each element is again an array of M elements.

Of course everything is kept simple now, in a latter version I'll more functions (like row access, column acces, transpose, copy, better initialization etc) and I'll add more complex things like SparseMatrix, Vectors, MatrixEnumerator etc.

I'll show now some code snippets , the full version can be downloaded here.

1. Matrix initialization


storage = [NSMutableArray arrayWithCapacity: j ] ;
for ( x = 0 ; x<=j ; x++ )
{

[storage insertObject: [NSMutableArray arrayWithCapacity: i ] atIndex: x] ;

for ( y = 0 ; y <= i ; y++)
{
// initialize each element with something
[[storage objectAtIndex: x]
insertObject: @"" atIndex: y ] ;

}
}


In the above snippet you see the initialization of a Matrix of size IxJ , as underlying datastructure I'll use the NSMutableArray.
Note that this initialization is oke for small matrices, and is usefull to be used in applications like chess or checkers.

2. Accessors for Matrix

Unfortunealy we don't have operator overloading like we have in C++ , but anyway. To access the elements of a matrix we have 2 accessors (a specialized get and set so to say).

- (void) atX: (int ) i atY: (int ) j put: (id) obj
{
//...
// store an element in the storage room
[[storage objectAtIndex: j]

replaceObjectAtIndex: i withObject: obj] ;
}


- (id) atX: (int ) i atY: (int ) j
{
//...
// get an element from the storage room
return [[storage objectAtIndex: j] objectAtIndex: i] ;

}


Now so far a basic matrix structure. Next time I'll go for some more advanced functions and structures.

Wednesday, 31 December 2008

Introduction to Objects - part II

First of all a happy 2009 for all of you !

In a previous blogmessage I explained a bit the concepts of objects.
Now another important concept is the way how objects communicate with each other.

The communication between objects happens by sending messages. If for example an object A wants to retrieve something from object B then A will have to send a message to B that B understands.

It looks a bit abstract but later on I'll show how that works in Objective-C.

Now their is a difference in a message and a method invocation. As already explaned an instance of class can be part of a whole class tree structure and as such a message can be implemented in different ways (=methods).
For example take a number of objects which are instances of the classes Point, Circle, Rectangle. To those objects you can send the message 'draw' , the actual method that will be invoked will be different for each object.

Note that in Objective-C you don't have to care about that, its the compiler/system that ensures that the right method is invoked.

Oke, this is enough theory, in a next message we'll start with some programming

Monday, 29 December 2008

Objective-C and Smalltalk

In a previous message I promised to discuss a more complex Cocoa/Obj-C application.

But afterwards I've realized that we should better discuss first of how to build a proper OO application.
To do this I will compare Obj-C with Smalltalk.

To my surprise Obj-C looks a lot like Smalltalk , but with a lot more syntax sugar.

So watch this blog to get a full understanding of OO, Obj-C and why Smalltalk is still the best OO-language in the world :-) :-)

Sunday, 28 December 2008

HelloWorld ?!? That was something

In the previous blog their where a few oddies that need some explanation :

In a typical Cocoa application you have what they call outlets and actions. And a view (=window) is connected to a controller.

Now an action is something you connected from the view to the controller. 
While an outlet is something you connect from the controller to the view.

A textfield, a list and so on are typically outlets because the controller will fill them. Buttons, comboboxes etc are more action oriented.

Something special is also the awakeFromNib function. As you see , I've added the code to initialize the textfield with HelloWorld in this function.

The awakeFromNib function can be seen as a placeholder where you can add initialization code to your GUI after the GUI is loaded. 

In a next blogmessage , I will publish a more complex application (well yeah , complex for the beginner)

For starters...

Anybody who starts with programming makes always the same first little program : the 'Hello World' application.

Well lets see how this works in Objective-C.

First start Xcode.
It's always a good practice to put your projects and builds in seperate directories. You can change this in XCode>Preferences>Building. 
Change the Build Products directory and the Intermediate Build directory.

If you done that , you can create a new Project (via XCode > File > New Project ) the project assistant will popup, choose 'Cocoa application'  and  call your new project HelloWorldProject.


As soon as you did that a project browser will show up (see below). 













Surprise ! You see a lot of files here, all this is generated by XCode.

Don't worry about them yet.

Let's first build our little HelloWorld application.

Start by double clicking the MainMenu.nib file, this will open the Interface Builder. When the interface builder, again a number of windows will open :
1. A blank window in which you'll design the UI
2. A palette with all types of UI controls (Cocoa -controls)
3. A menu-bar
4. The mainmenu nib itselfs

Start with dragging a text field from the Cocoa-controls to the blank menu (the text field controls can be found by clicking the third item on the menu bar of the Cocoa-controls window).

Now the first part of the helloworld application is done.

The second part consists of the creation of a controller. Now here we need some theory.
In fact what we want is an implementation of the Model-View-Controller design pattern.

In our case we have built a View with the Interface Builder and now we need to put some logic behind to do something useful. This logic we will put in a controller.

The setup of a controller is again pretty straightforward :

In the Mainmenu window you select 'classes' and look for the class NSObject (see screenshot below) 


Now up in the menu you select 'Classes>Subclass NSObject'. A new class will appear , you can rename it to HelloWorldController.
Now we need to create the files in which we will write Objective-C code.
Therefore you you go to the menu and select 'Classes>Create Files for HelloWorldController'. A popup will appear, let everything default and press the 'choose' button.

The next thing you must do is to instantiate that class (otherwise your newly created view won't work).

To do this you first select your newly created controller (HelloWorldController) and then you select from the menu 'Classes>Instantiate HelloWorldController'.

Voila we are almost there ! Now we need some coding.

A first step is to create an outlet in the controller class. This you do by selecting the HelloWorldController class in the class browser.
And then in the menu you select 'Classes>Add outlet to HelloWorldController'.

A popup will appear in which you can define the outlet (call it sayHello) .

Once the outlet is created we need to link it to the text field.

This is done by selecting the HelloWorldController instance in mainmenu window.
You then CTRL-Click the HelloWorldController (keep mouse button pressed) and drag to the text field (a blue line will appear). Release the mouse and a popup will appear, in this popup you see all the outlets defined (in your case only one) .

Now connect the sayHello outlet by clicking the 'connect' button.

Now we are done with interface builder, use Command-Q to quit it ( he will ask first to save all your work).

In the XCode project browser you'll see 2 new files, HelloWorldController.h and HelloWorldController.m.

In the .h file you should add the following line (between the { } ) :

IBOutlet id sayHello ;

In the .m file you should add the following method  (after the @implementation line) :

- (void) awakeFromNib
{
[sayHello setStringValue: @"Hello World" ];

}


Now build and run this application, and YESSSS you see that 'Hello World' appears