I think you already know how does it look like. Before making a real game, why don't we draw something by changing the code in TankGameView.drawRect to know the basic drawing techniques.
Basic drawings
Before letting it draw, take a look at the code in the template to know what is going on.
def drawRect()
# 1. Fill background
NSColor.blackColor.set
NSRectFill(@bounds)
# 2. Set shadow for objects
setShadow(NSColor.lightGrayColor, [6.0, -6.0], 0.7, 0.6)
# 3. Draw a string
drawCenterizedText("Draw Something", 80, NSColor.whiteColor)
end
This method is automatically invoked after an event process (like TankGameState.keyDown or TankGameState.tick ). The main things it does are shown below.
- Fill background
This is the typical code seen in many Cocoa games. The first line sets the background to black. The second line fills the whole display in the window. @bounds is an NSRect object that represents the origin and size of this view. - Set shadow for objects
This code makes shadows underneath all subsequent drawing objects. The game framework provides ShadowMaker module so you can call setShadow to set the shadow. Arguments for the method are: (1) color (NSColor object), (2) offset (NSPoint object), (3) blur diameter (Float), and (4) alpha value (0.0 - 1.0). See ShadowMaker module for further information - Draw a text string
This code draws "Draw Something" at the center of the window. See TextMaker module for further information.
To draw something in your game, you must write drawing procedures in this method or in some other methods that are called from this method.
Drawing shapes
There are lots of objects you draw in a game. In drawRect method, you can draw as many objects as you want by using Cocoa frameworks drawing objects such as NSBezierPath, NSImage, and NSString. This section shows how to draw these objects in drawRect method.
Drawing a rectangle
You can draw a rectangle by using NSRectFill function. The code would be like this.
NSColor.whiteColor.set NSRectFill(NSRect.new([x, y], [width, height]))
You can also use NSBezier.bezierPathWithRect to draw a rectangle. See NSBezierPath class reference for more detail.
Drawing a polygon
To draw a polygon, using NSBezierPath will get the job done. The code below will draw a small white triangle.
NSColor.yellowColor.set path = NSBezierPath.bezierPath point = NSPoint.new(100, 100) path.moveToPoint(point) [[150, 150], [200, 100], [100, 100]]].each do |point| path.lineToPoint(NSPoint.new(*point)) end path.stroke
You can designate as many points as you want to draw more complex shapes. Using path.fill instead of path.stroke will draw a filled triangle. In this case, you don't need the last point.
Drawing an oval
The code below will draw a blue oval at the point (100, 100) where its width and height are 200 and 150 respectively.
NSColor.blueColor.set rect = NSRect.new(NSPoint.new(100, 100), NSSize.new(200, 150)) path = NSBezierPath.bezierPathWithOvalInRect(rect)
As same as drawing polygons, you can write path.fill to get a filled oval. For more detail about BezierPath, see NSBezierPath class reference.
Drawing an image
To draw an image in you game, using NSImage is the easiest way. The code to draw an image "Elephant.tiff" at the center of the view would be like this:
image = NSImage.alloc.initByReferencingFile("/Users/me/images/Elephant.tiff")
point = Field.centerizedPoint(image.size)
image.compositeToPoint(point,:operation, NSCompositeSourceOver)
If you want to draw an image that is stored in Resources folder under your application path, you can use NSImage.imageNamed to create an image object. To make an image object for "Elephant.tiff" in the resource folder would be like this:
image = NSImage.imageNamed("Elephant")
See NSImage class reference for more detail.
Drawing a text string
As shown in the code at the beginning of this page, you can use drawCenterizedText to draw a text string. The following code will draw "How are you?" at the center of the window.
drawText("How are you?", 70, NSColor.whiteColor);
You can also use drawText defined in TextMaker module that is included in the View class. The following code will draw "Hello" at the point (100, 100):
drawText("Hello", 100, NSColor.white, NSPoint.new(100, 100))
See TextMaker module for more details.
Making shadows
To make shadows for drawing objects, simply use the setShadow method. Arguments for the method are: (1) color (NSColor object), (2) offset (NSPoint object), (3) blur diameter (Float), and (4) alpha value (0.0 - 1.0). The code below makes shadows with lightGrayColor at offset (6.0, -6.0).
setShadow(NSColor.lightGrayColor, [6.0, -6.0], 0.7, 0.6)
Blur diameter is set to 0.7 (very clear) and opacity is set to 0.6 (about half transparent). You should call this method before drawing any objects.
Let it Draw these objects
Here shows the code for drawing all the objects above.
def drawRect()
NSColor.blackColor.set
NSRectFill(@bounds)
setShadow(NSColor.lightGrayColor, [6.0, -6.0], 0.7, 0.6)
NSColor.whiteColor.set
NSRectFill(NSRect.new([100, 300], [100, 150]))
NSColor.yellowColor.set
path = NSBezierPath.bezierPath
point = NSPoint.new(100, 100)
path.moveToPoint(point)
[[150, 150], [200, 100], [100, 100]].each {|point| path.lineToPoint(NSPoint.new(*point)) }
path.fill
NSColor.blueColor.set
rect = NSRect.new(NSPoint.new(400, 100), NSSize.new(200, 150))
path = NSBezierPath.bezierPathWithOvalInRect(rect)
path.fill
image = NSImage.alloc.initByReferencingFile("/Applications/MiniKidsGames.app/Contents/Resources/Elephant.tiff")
point = Field.centerizedPoint(image.size)
point.y += @bounds.size.height / 4;
image.compositeToPoint(point,:operation, NSCompositeSourceOver)
drawCenterizedText("I drew 'em", 80, NSColor.whiteColor,
NSPoint.new(0, -@bounds.size.height / 4)
end
Now run the application and select TankGame. You will see the window shown as below.
Inside the Game Framework - How the game framework invokes drawRect()
Now you know how to draw objects at TankGameView.drawRect. But you may wonder from where and from whom this method is called.
The game framework invokes Game.drawRect:
- after a timer event is handled
- after a key event is handled
- after a mouse event is handled
When an event occurs, the framework creates an Event object (one of KeyEvent, TimerEvent, or MouseEvent). The Event object, then, calls event handler in the current State object. At the time the event handler finishes its process, the event object requests MiniGamesView, the top-level view of MiniKidsGames, to redraw if the event handler returns true. Finally, MiniGamesView invokes drawRect method in the current View object.
You may have another question: "how does MiniGamesView know the current View?" The answer for this question is that MiniGamesView asks the Game class to get the current View. The Game class is a super class for all the games, which contains binding information among View, Model, and State classes.
If you want to know more detail about this mechanism, take a look at MiniGamesView.rb. Reading the code at drawRect will tell you much more information.
What we've created so far
is the file that we made so far. Rename the file to "TankGame.rb" and copy it to the project folder so you can take a look at what's going on.








