Posted: August 10th, 2010 | Author: Remi | Filed under: Cocoa, OS X, Programming | No Comments »

Completed Project
Recently I was working on a project where I wanted a certain effect. This was that I wanted the user to be able to delete items out of a table by clicking on the item and not having to add some button somewhere else to do it. So the answer was to put a button on the table to delete it. That was simple enough, just make a table with button cells, but it didn’t look very nice, it showed all the button when you could only delete one at a time. So thus, I decided to make the buttons only appear on the selected table items. Its simple, functional, and you can do it too if you just follow this short guide.
To tackle this problem, there are two “hacks” that we need to do. First, we have to somehow make the NSButtonCell hide itself. Next, we have to keep track of which row is selected, and tie that information back to our buttons. To accomplish the first task, will tie the button being hidden to it’s enabled value, since this way is easier then creating a new binding, and it doesn’t matter is the button is disabled if it’s hidden anyway. Subclass NSButtonCell and override this method with this code.
- (void) drawWithFrame: (NSRect)cellFrame inView: (NSView*)controlView
{
if([self isEnabled])
[super drawWithFrame:cellFrame inView:controlView];
} |
In interface builder, drag a NSButtonCell to one of the columns of your NSTableView. (Apple hides it as a ‘Check Box Cell’, see below, you have to change the type to ‘Momentary Push In’).

Check Box Cell (NSButtonCell)

Setting the Class to HidingButtonCell
Change the class to your custom subclass. Next we need to somehow get the data in a form we can bind to the button’s enabled key. There are potentially a couple ways to do this, but I decided to subclass NSTableView, and override this method.
- (void)selectRowIndexes:(NSIndexSet *)indexes byExtendingSelection:(BOOL)extend
{
[super selectRowIndexes:indexes byExtendingSelection:extend];
[controller setSelectionIndex:[indexes firstIndex]];
int i;
for(i = 0; i < [[controller arrangedObjects] count]; i++)
{
[[[controller arrangedObjects] objectAtIndex:i] setObject:
[NSNumber numberWithInt:[indexes firstIndex] == i] forKey:@"enabled"];
}
} |
Of, course this way of doing this assumes you’re binding to an NSArray of NSMutableDictionaries. Next, back in Interface Builder we can bind the column to the new data that’s going to be generated with that method. And thats it enjoy you’re disappearing buttons. If you want the button to delete the row, like mine, just connect the NSButtonCell’s action to the NSArrayController’s remove: method. If I made any mistakes, or made anything unclear, please leave a comment. For a closer look, Download the Xcode Project
Posted: July 18th, 2010 | Author: Remi | Filed under: Cocoa, Programming, iPhone | No Comments »
As promised, here is some example code for the iPhone using ThoMoNetworking. I call it Remi’s Chat App. The mobile companion to Remi’s Chat Program.

Sorry it took me so long to put it up. Some things to note: It interfaces with Remi’s Chat Program in everything except that iOS doesn’t support the rich text. You may notice if you download the project that I created a file called NSPatches, this was to allow for the iOS to properly unarchive some classes that it doesn’t have, most notably NSFont. Other then that, from what I can tell ThoMoNetworking works flawlessly on iOS. The only thing I couldn’t test was from iOS to iOS, since I lacked two iOS devices, but from iOS to OS X worked great, so I would assume it would work fine. So here is the bulk of the code for you to peruse, and you can download the project underneath, enjoy!
P.S. Let me know if anybody runs into any issues with the code, I may be able to resolve them easily, since some crashes might just be due to iOS not having certain clases that OS X has, which a simple appending to the NSPatches file should fix.
//
// Remi_s_Chat_AppViewController.m
// Remi's Chat App
//
// Created by Remi Bernotavicius on 7/18/10.
// Copyright __MyCompanyName__ 2010. All rights reserved.
//
#import "Remi_s_Chat_AppViewController.h"
@implementation Remi_s_Chat_AppViewController
/*
// The designated initializer. Override to perform setup that is required before the view is loaded.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
// Custom initialization
}
return self;
}
*/
/*
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView {
}
*/
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
myServer = [[ThoMoServerStub alloc] initWithProtocolIdentifier:@"remischat"];
[myServer setDelegate:self];
[myServer start];
myClient = [[ThoMoClientStub alloc] initWithProtocolIdentifier:@"remischat"];
[myClient setDelegate:self];
[myClient start];
[[UIApplication sharedApplication] setDelegate:self];
}
- (void)applicationWillTerminate:(UIApplication *)application
{
NSMutableAttributedString* temp = [[[NSMutableAttributedString alloc] initWithString:[NSFullUserName() stringByAppendingString:@" disconnected"]] autorelease];
[temp appendAttributedString:[[[NSAttributedString alloc] initWithString:@"\n"] autorelease]];
[myServer sendToAllClients:temp];
}
- (void)server:(ThoMoServerStub *)theServer acceptedConnectionFromClient:(NSString *)aClientIdString;
{
NSMutableAttributedString* temp = [[[NSMutableAttributedString alloc] initWithString:[NSFullUserName() stringByAppendingString:@" connected"]] autorelease];
[temp appendAttributedString:[[[NSAttributedString alloc] initWithString:@"\n"] autorelease]];
[myServer send:temp toClient:aClientIdString];
}
/*
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
*/
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
CGRect newFrame = self.view.frame;
if ([[UIApplication sharedApplication] statusBarOrientation]== UIInterfaceOrientationPortrait
|| [[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationPortraitUpsideDown)
newFrame.size.height -= 216;
else
newFrame.size.height -= 162;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:0.3];
[self.view setFrame:newFrame];
[UIView commitAnimations];
}
-(IBAction)sendMessage:(id)sender
{
NSMutableAttributedString* temp = [[[NSMutableAttributedString alloc] initWithString:[NSFullUserName() stringByAppendingString:@": "]] autorelease];
[temp appendAttributedString:[[[NSMutableAttributedString alloc] initWithString:toSend.text] autorelease]];
[temp appendAttributedString:[[[NSMutableAttributedString alloc] initWithString:@"\n"] autorelease]];
[myServer sendToAllClients:temp];
toSend.text = @"";
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
CGRect newFrame = self.view.frame;
if ([[UIApplication sharedApplication] statusBarOrientation]== UIInterfaceOrientationPortrait
|| [[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationPortraitUpsideDown)
newFrame.size.height += 216;
else
newFrame.size.height += 162;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:0.3];
[self.view setFrame:newFrame];
[UIView commitAnimations];
}
-(void)server:(ThoMoServerStub *)theServer didReceiveData:(id)theData fromClient:(NSString *)aClientIdString {}
-(void)client:(ThoMoClientStub *)theClient didReceiveData:(id)theData fromServer:(NSString *)aServerIdString;
{
NSMutableAttributedString* temp = [[[NSMutableAttributedString alloc] initWithAttributedString:theData] autorelease];
history.text = [history.text stringByAppendingString:[temp string]];
[history scrollRangeToVisible:NSMakeRange([history.text length]-2, 1)];
}
- (void)dealloc {
[super dealloc];
}
@end |
Download the Xcode Project
Posted: June 8th, 2010 | Author: Remi | Filed under: Cocoa, Programming | 2 Comments »
I happened to stumble upon an amazing framework called ThoMoNetworking. It takes the complicated task of networking in Cocoa and makes it extremely easy. Basically it lets you define your own protocol and connects to other instances of it on the network automatically using bonjour. Then to send data it allows you to send objects. The potential from this framework is huge, especially since it works on both iPhone OS and Mac OS. It is incredibly simple, check out their website for how to use it, it is outlined in its full simplistic beauty.
With such a powerful framework at my disposal, I decided to test it out. I wanted to see just how easy it would be to create my own ad-hoc chatting program. I’ve included the source as well so you can test out the framework for yourselves.
I give you, Remi’s Chat Program

Since ThoMoNetworking lets you send any object, I was able to send NSAttributedString objects, so the text’s color and font are preserved. I was also able to include recalling previously sent messages with the arrow keys (like in the terminal) and growl support as a superfluous features. This seemingly complicated program is actually very little code.
//
// Remi_s_Chat_ProgramAppDelegate.m
// Remi's Chat Program
//
// Created by Remi Bernotavicius on 6/1/10.
// Copyright 2010 __MyCompanyName__. All rights reserved.
//
#import "Remi_s_Chat_ProgramAppDelegate.h"
@implementation Remi_s_Chat_ProgramAppDelegate
- (NSDictionary *) registrationDictionaryForGrowl {
NSArray *array = [NSArray arrayWithObjects:@"new message", nil];
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:1],
@"TicketVersion",
array,
@"AllNotifications",
array,
@"DefaultNotifications",
nil];
return dict;
}
-(void) growlAlert:(NSString *)message title:(NSString *)title{
[GrowlApplicationBridge notifyWithTitle:title
description:message
notificationName:@"new message"
iconData:[[[NSApplication sharedApplication] applicationIconImage] TIFFRepresentation]
priority:0
isSticky:NO
clickContext:@"bringFrontContext"];
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
[GrowlApplicationBridge setGrowlDelegate:self];
myServer = [[ThoMoServerStub alloc] initWithProtocolIdentifier:@"remischat"];
[myServer setDelegate:self];
[myServer start];
myClient = [[ThoMoClientStub alloc] initWithProtocolIdentifier:@"remischat"];
[myClient setDelegate:self];
[myClient start];
[[NSApplication sharedApplication] setDelegate:self];
previousChats = [[NSMutableArray alloc] init];
current = 0;
}
- (void)server:(ThoMoServerStub *)theServer acceptedConnectionFromClient:(NSString *)aClientIdString;
{
NSMutableAttributedString* temp = [[[NSMutableAttributedString alloc] initWithString:[NSFullUserName() stringByAppendingString:@" connected"]] autorelease];
[temp addAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[NSFont boldSystemFontOfSize:12], NSFontAttributeName, nil] range:NSMakeRange(0, [temp length])];
[temp appendAttributedString:[[[NSAttributedString alloc] initWithString:@"\n"] autorelease]];
[myServer send:temp toClient:aClientIdString];
}
-(void)dealloc
{
[previousChats release];
[super dealloc];
}
-(void)retreat
{
if(current < [previousChats count]) { current++; [[toSend textStorage] setAttributedString:[previousChats objectAtIndex:current]]; if(current == [previousChats count]-1) [previousChats removeLastObject]; } } -(void)advance { if(current > 0 && [previousChats count] > 0)
{
if(current > [previousChats count]-1)
[previousChats addObject:[[toSend attributedString] copy]];
current--;
[[toSend textStorage] setAttributedString:[previousChats objectAtIndex:current]];
}
}
- (void)windowDidBecomeKey:(NSNotification *)notification
{
[mainWindow makeFirstResponder:[toSend superview]];
}
-(IBAction)sendMessage:(id)sender
{
NSMutableAttributedString* temp = [[[NSMutableAttributedString alloc] initWithString:[NSFullUserName() stringByAppendingString:@": "]] autorelease];
[temp appendAttributedString:[toSend attributedString]];
[previousChats addObject:[toSend attributedString]];
if ([previousChats count] <= 10)
current = [previousChats count];
else
[previousChats removeObjectAtIndex:0];
NSString* t = [temp string];
if(![[t substringWithRange:NSMakeRange([t length]-1, 1)] isEqual:@"\n"])
[temp appendAttributedString:[[[NSAttributedString alloc] initWithString:@"\n"] autorelease]];
[myServer sendToAllClients:temp];
[[toSend textStorage] setAttributedString:[[[NSAttributedString alloc] initWithString:@""] autorelease]];
}
- (void) growlNotificationWasClicked:(id)clickContext{
[[NSApplication sharedApplication] activateIgnoringOtherApps:YES];
}
-(void)server:(ThoMoServerStub *)theServer didReceiveData:(id)theData fromClient:(NSString *)aClientIdString {}
-(void)client:(ThoMoClientStub *)theClient didReceiveData:(id)theData fromServer:(NSString *)aServerIdString;
{
NSMutableAttributedString* temp = [[[NSMutableAttributedString alloc] initWithAttributedString:[history attributedString]] autorelease];
[temp appendAttributedString:theData];
[[history textStorage] setAttributedString:temp];
[history scrollRangeToVisible:NSMakeRange([[history textStorage] length], 0)];
if(![mainWindow isKeyWindow])
{
[[NSApplication sharedApplication] requestUserAttention:NSCriticalRequest];
[self growlAlert:[(NSAttributedString*)theData string] title:@"New Message"];
}
}
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
{
NSMutableAttributedString* temp = [[[NSMutableAttributedString alloc] initWithString:[NSFullUserName() stringByAppendingString:@" disconnected"]] autorelease];
[temp appendAttributedString:[[[NSAttributedString alloc] initWithString:@"\n"] autorelease]];
[temp addAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[NSFont boldSystemFontOfSize:12], NSFontAttributeName, nil] range:NSMakeRange(0, [temp length])];
[myServer sendToAllClients:temp];
return NSTerminateNow;
}
@end |
Download the Xcode Project
Let me know if there are any issues with the source, or if you would like to see more, like an iPhone OS example, just post a comment.
Posted: May 15th, 2010 | Author: Remi | Filed under: Cocoa, OS X, Programming | No Comments »
I was playing the fabulous typing game TypeRacer when I thought that it would be fun to type some sort of other text. I decided to try making my own typing program. So I threw together this new typing game for OS X that lets you type random paragraphs of text from wikipedia. Its absolutely free, try downloading it here Download Page.

WikiTyper in Action
If you have any comments on the game please post them below. Some things I know are not working and I might fix in the future if people ask about them. The words per minute is actual words per minute not the correct wpm, (if anyone knows the formula?) Also occasionally it will display characters that you cannot type, but I couldn’t find a way to remedy that efficiently. Finally, for those of you Linux and Windows users, a Java port is being made by someone else. I will post a link if/when it is finished.
Posted: November 14th, 2009 | Author: Remi | Filed under: Cocoa, Programming | 1 Comment »
In Cocoa KVO or Key-Value-Observing compliant means that the value of a certain object sends notifications out when its value has been changed to an observer. An example would be values stored in a NSMutableDictionary or NSMutableArray. Since they are KVO compliant, you can bind something to a value in one of these objects, and will be updated automatically, no glue code required. Although not all objects have their values KVO compliant and this can cause problems for example when trying to bind to them in Interface Builder. A good example can be seen with NSDocument’s documentName. Notice you can bind an object’s value to documentName, but if the documentName changes, this value does not update. The way to fix this, is to subclass NSDocument and send out notifications whenever documentName is changed. A class-dump of NSDocument reveals the -(BOOL)_setDocumentName:(NSString*)name method. All you have to do is add this method to your NSDocument subclass
-(void)_setDisplayName:(NSString*)name
{
//Hack Display Name to make KVO Compliant
[self willChangeValueForKey:@"displayName"];
[(YourClassNameHere*)super _setDisplayName:name];
[self didChangeValueForKey:@"displayName"];
} |
And that should be it. Note: I changed the method’s return type to void because otherwise it will create an error in the console about KVO compliant methods not being able to return anything other then void.
Also note that this is for read-only binding, to do a binding where you can change the value you have to implement and expose a new binding programmatically.
Apple’s Documentation on KVO
Posted: August 12th, 2009 | Author: Remi | Filed under: Programming, Site News | No Comments »
Just recently, I’ve gotten into making pages XHTML 1.0 Transitional compliant. What this means is that the coding of the webpage is fit to a more strict standard then just plain HTML. Practically speaking this means that the webpage fits into the web standards and will close guarantee that your webpage will display correctly on current and future web-standard compliant browsers. There are three types of XHTML, Transitional, Strict, and Frameset. Transitional is most widely used form of XHTML, and Strict is a version that is even more, well, strict. Making pages XHTML 1.0 Strict compliant can be difficult, but making it Transitional compliant isn’t hard at all. It is mainly a matter of cleaning up your existing HTML. I will cover how to make your webpage XHTML 1.0 Transitional compliant, as I have done with my site. But, don’t take my word, try clicking the button on the right that says “W3C XHTML 1.0″ and it will go to W3C’s (the organization that makes the web standard) xhtml/html validator. This is an extremely helpful tool, because it highlights the errors in your webpage that make it not xhtml compliant.
The first thing you must do is specify a doctype, here it is for transitional
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> |
Next comes the hmtl tag, but what you have to do in it is define the XML name space and the language as english
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en:gb"> |
Now add the head tag, specify the page encoding, and add a title which is required in valid XHTML
<head profile="http://gmpg.org/xfn/11">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Hello World!</title> |
For the most part all of your XHTML Transitional pages should start that way. The next thing to do is just to take care of some pretty simple formatting rules. First off, all of your tags must be in lowercase, and this goes for your tag’s properties too, for example onClick is bad, it has to be onclick, and <P> has to be <p>. Next all your tags have to be closed, if you’re use to using single <p> tags, you’ll have to do them in the self-closing style: <p />. Script and style tags must contain a type, so like the following,
<script type="text/javascript"></script>, <style type="text/css"></style> |
Also JavaScript not in an external file has to be escaped properly from the XHTML interpreter like follows:
<script type="javascript">
//<![CDATA[
alert("Hello");
//]]>
</script> |
Image tags also, have to be closed but also they have to include the alt attribute, even if its just blank.
<img src="http://kunugiken.com/DRF/refresh.png" alt="" /> |
Another interesting thing to note is that when you declare your page as XHTML, is can break some of your CSS if it is not done correctly, one example would be the left property, for example the following will work in most browsers, but will not work on XHTML pages
position: absolute;
left: 40; |
In actuality the left, top, right or bottom properties take a numerical value with a unit of measurement, so it has to be the following
position: absolute;
left: 40px; |
Remember that this is also true if you’re setting the CSS from inside JavaScript.
I hope that you found this helpful, these are just some of the things that caught me up while converting my site to XHTML. Although it wasn’t so hard to make my blog part of the site proper XHTML because wordpress does a nice job of making XHTML compliant code anyway. (Although I had to mess with some of the plugins to get them to do it right). Check out W3School’s page on XHTML, and try taking their quiz! I hope you found XHTML at least interesting, and will consider converting your pages. Good Luck Everyone.
Posted: December 7th, 2008 | Author: Remi | Filed under: Programming | 7 Comments »
When it comes to simple 2D game programming Allegro is great. It may be a little tricky to get allegro to install on some systems, but I will cover how to do it on three: Ubuntu, OS X and Windows.
We’ll be starting with the easiest, Ubuntu
Open up the terminal (Applications > Accessories > Terminal) and type if you have not already
sudo apt-get install build-essential
Then we’ll install Allegro:
sudo apt-get install liballegro4.2-dev
Thats it, allegro is installed and gcc is ready to compile allegro source.
To compile and run file by name inputfile.c in gcc type:
gcc inputfile.c -o output `allegro-config --libs`
./output
On OS X it is a little tricker, and I highly recommend installing X-Code to compile the code with, there is a way to install gcc without X-Code, but I don’t recommend it, and I won’t cover it here.
download X-Code here (You have to become an ADC member to download, it’s free). You can also install X-Code (developer tools) from your OS X installation disk.
download the allegro source for Unix on their website here
its a tar.gz so, double click it and it should be expanded into a folder.
Now open the terminal (/Applications/Utilities/Terminal) and type “cd ” then drag the allegro folder to the window and hit enter, now type the following:
chmod +x fix.sh
./fix.sh macosx
make
sudo make install
sudo make install-man
sudo make install-framework
sudo make install-framework EMBED=1
sudo make install-template
If you are using X-Code 3.0 or higher then type the following to make the template work:
mv /Library/Application\ Support/Apple/Developer\ Tools/Project\ Templates/Application/Allegro\ Application /Developer/Library/Xcode/Project\ Templates/Application
There, you’re done, now all you need to do is open X-Code and then click File > New Project then under application choose allegro application.
For windows, you can install Allegro to work with Visual C++ or other Microsoft IDE’s if you use them for development, but if you don’t have any of those don’t fret, just download and install Bloodshed’s Dev-Cpp here
Then to install allegro, download the allegro devpak here and then just double click it.
Once it installs you should be set, now just open Dev-Cpp and make a new allegro project.
Here is some code you can try and compile, it’s a version of pong I wrote for allegro, it’s still buggy so beware!
/*
* Pong
*
* Created by Remi Bernotavicius on 12/4/08.
* Copyright (c) 2008 __MyCompanyName__. All rights reserved.
*/
#include <allegro.h>
#include <math.h>
#define paddle_width 10
#define paddle_height 50
#define screen_width 640
#define screen_height 400
#define ball_speed 70
#define ball_size 6
#define paddle_speed 15
#define dashed_frequency 20.00
#define UP 0
#define CENTER 1
#define DOWN 2
//left side
int yl = ((screen_height / 2) - (paddle_height/2))*paddle_speed;
int points_l = 0;
int direction_l = CENTER;
//right side
int yr = ((screen_height / 2) - (paddle_height/2))*paddle_speed;
int points_r = 0;
int direction_r = CENTER;
//ball
int bx = (screen_width / 2)*ball_speed;
int by = (screen_height / 2)*ball_speed;
int angle = 30;
int i_speed = 5;
int rest_counter = 0;
void gatherInput()
{
if(key[KEY_DOWN] && yr < (screen_height - paddle_height)*paddle_speed)
{
yr++;
direction_r = DOWN;
}
else if(key[KEY_UP] && yr > 0)
{
yr--;
direction_r = UP;
}
else
{
direction_r = CENTER;
}
if(key[KEY_Z] && yl < (screen_height - paddle_height)*paddle_speed)
{
yl++;
direction_l = DOWN;
}
else if(key[KEY_A] && yl > 0)
{
yl--;
direction_l = UP;
}
else
{
direction_l = CENTER;
}
}
int main(int argc, const char *argv[])
{
allegro_init();
install_keyboard();
if (set_gfx_mode(GFX_AUTODETECT, screen_width, screen_height, 0, 0)) {
allegro_message("Error setting 320x200x8 gfx mode:\n%s\n", allegro_error);
return -1;
}
//Title Screen
textprintf_centre_ex(screen, font, screen_width/2, 100, makecol(255, 255, 255), -1,
"Pong!");
textprintf_centre_ex(screen, font, screen_width/2, 120, makecol(255, 255, 255), -1,
"By Remi Bernotavicius");
textprintf_centre_ex(screen, font, screen_width/2, 140, makecol(255, 255, 255), -1,
"Press Space Bar to Start");
while(!key[KEY_SPACE])
{
if(key[KEY_ESC])
return 0;
}
BITMAP* buffer = create_bitmap(screen_width, screen_height);
while(!key[KEY_ESC])
{
gatherInput();
clear_to_color(buffer, 0);
//score
textprintf_centre_ex(buffer, font, screen_width/4, 10, makecol(255, 255, 255), -1, "%d",
points_l);
textprintf_centre_ex(buffer, font, screen_width*(3.00/4.00), 10, makecol(255, 255, 255), -1,
"%d", points_r);
//dashed line
float f;
for(f = 1.00;f < dashed_frequency;f +=2.00)
line(buffer, screen_width/2, -10 + screen_height - (screen_height*(f/dashed_frequency)) +
(screen_height*(1.00/dashed_frequency)), screen_width/2, -10 + screen_height -
(screen_height*(f/dashed_frequency)), makecol(255, 255, 255));
//left paddle
rectfill(buffer, 10, yl/paddle_speed, 10+paddle_width, (yl/paddle_speed)+paddle_height,
makecol(255, 255, 255));
//right paddle
rectfill(buffer, screen_width - 10 - paddle_width, yr/paddle_speed, screen_width - 10,
(yr/paddle_speed)+paddle_height, makecol(255, 255, 255));
while(angle > 360)
angle -= 360;
while(angle < -360)
angle += 360;
if(rest_counter == 0)
{
bx+=cos(angle*M_PI/180)*i_speed;
by+=sin(angle*M_PI/180)*i_speed;
}
else
{
rest_counter--;
}
circlefill(buffer, bx/ball_speed, by/ball_speed, ball_size,
makecol(250, 250, 250));
//collision detection
if((by/ball_speed) > screen_height - ball_size)
{
angle *= -1;
by = (screen_height - ball_size)*ball_speed;
}
else if((by/ball_speed) < ball_size)
{
angle *= -1;
by = ball_size * ball_speed;
}
if((bx/ball_speed) > (screen_width - 10 - paddle_width - ball_size))
{
if((by / ball_speed) > ((yr/paddle_speed) - ball_size) && (by / ball_speed) <
(((yr/paddle_speed) + paddle_height) + ball_size))
{
//If the ball hit the right paddle
angle *= -1;
angle += 180;
if(direction_r == UP)
{
angle += 30*sin(angle*M_PI/180);
i_speed -= 2*sin(angle*M_PI/180);
}
else if(direction_r == DOWN)
{
angle -= 30*sin(angle*M_PI/180);
i_speed += 2*sin(angle*M_PI/180);
}
bx = (screen_width - 10 - paddle_width - ball_size)*ball_speed;
}
else
{
//If the ball went off the screen on the right
points_l++;
bx = (screen_width/2)*ball_speed;
by = (screen_height/2)*ball_speed;
angle = 30;
i_speed = 5;
rest_counter = 3000;
}
}
else if((bx/ball_speed) < 10 + paddle_width + ball_size)
{
if((by / ball_speed) > ((yl/paddle_speed) - ball_size) && (by / ball_speed) <
(((yl/paddle_speed) + paddle_height) + ball_size))
{
//If the ball hit the left paddle
angle *= -1;
angle += 180;
if(direction_l == UP)
{
angle -= 30*sin(angle*M_PI/180);
i_speed -= 2*sin(angle*M_PI/180);
}
else if(direction_l == DOWN)
{
angle += 30*sin(angle*M_PI/180);
i_speed += 2*sin(angle*M_PI/180);
}
bx = (10 + paddle_width + ball_size)*ball_speed;
}
else
{
//If the ball went off the screen on the left
points_r++;
bx = (screen_width/2)*ball_speed;
by = (screen_height/2)*ball_speed;
angle = 150;
i_speed = 5;
rest_counter = 3000;
}
}
blit(buffer, screen, 0, 0, 0, 0, screen_width, screen_height);
}
return 0;
}
END_OF_MAIN(); |
Download
Posted: November 16th, 2008 | Author: Remi | Filed under: Programming | 1 Comment »
At my school’s computer club we are doing a comparison of different programming languages.
We took a simple program written in BASIC and examined how it works. Then I translated it to both C and Javascript.
Here is the program in BASIC which is a procedural language, unlike non-scripting languages it is non-compiling, this means that it is translated to code the machine can understand one line at a time when the program is actually run. Because of this, it is incredibly slow when compared to modern languages like C.
DIM r, q, p, m
INPUT "What interest do you expect? ", r
INPUT "How much % do you withdraw per year? ", q
p = 1! 'Principle
m = 0! 'number of months so far
DO WHILE (p > 0!)
FOR i = 1 TO 12
p = p + ((r / 1200) * p) - ((q / 1200) * 1)
IF (p < 0) THEN PRINT "your number of years = "; m / 12 i = 12 END IF m = m + 1 NEXT i IF m > 1200 THEN
PRINT "you won't live that long!!!"
p = -1!
END IF
LOOP |
Here it is in C, another procedural language.
To compile on Unix or Linux based computers, type in a terminal
gcc path/to/sourcefile.c -o output_program
then to run it
./output_program
#include
int main()
{
float r, q, p, m;
printf("\nWhat interest do you expect? ");
scanf("%f",&r);
printf("\nHow much %% do you withdraw per year? ");
scanf("%f",&q);
p = 1.00; //Principle
m = 0.00; //Number of months so far
int i;
while(p > 0.00)
{
for(i = 0;i <= 12;i++)
{
p += ((r / 1200) * p) - (q / 1200);
if(p < 0) { printf("\nyour number of years = %f\n", m/12); i = 12; } m += 1; } if(m > 1200)
{
printf("\nyou won't live that long");
p = -1.00;
}
}
return 1;
} |
And here it is in Javascript, an object-oriented scripting language. Although basically since this program is so simple, and there was no need to use objects except document, it looks almost identical to the program in C. Test Out The Javascript Here
<script type="text/javascript"><!--mce:0--></script>
<form id="theForm">
What interest do you expect?
<input id="r" type="text" />
How Much % do you withdraw per year?
<input id="q" type="text" />
<input type="submit" value="Calculate" />
</form>
<div id="result"></div> |
After looking at the code for all three, it seems that they are for the most part very similar. The syntax from BASIC to C is quite different, but they both use loops and if statements. One difference that can be seen particularly in this program is the lack of variable types in BASIC. You can see in C that we have to declare the variables as float so that they will hold a decimal. Another difference is that there is no shortcut it seems in BASIC for variable = variable + number; as there is in C. As you can see in C it goes like variable += number; . Also it is worth nothing that comments in BASIC use a single quote mark ( ‘ ) to denote comments, while almost all more modern languages use the double forward slash ( // ). And of course, BASIC doesn’t use braces at all. Instead it has a sort of tag way of enclosing statements. These are just some of the differences. A lot of languages used nowadays follow after C, the javascript is the case in point. It is always worth looking at older languages to really see if the way languages today do things is really better or not.
Try it out for yourself and see the differences
Download Source for All Three