• Hey, guest user. Hope you're enjoying NeoGAF! Have you considered registering for an account? Come join us and add your take to the daily discourse.

Programming |OT| C is better than C++! No, C++ is better than C

Granadier

Is currently on Stage 1: Denial regarding the service game future
The actual official developer documentation / getting started stuff is fine, I meant it's lacking in the wider context of the web as a whole.

There are lots of blogs with great snippets and tutorials dotted around too, but as they tend to either be personal, or app-based the useful stuff is often bookended with random, less android-focused blog posts.

But as for sites dedicated to android development on the whole, that's where I feel it lacks presence.

Ahh, ok I understand where you're coming from now.
That has been my experience as well, and I agree with you.
Be sure to post here if you end up creating a site dedicated to it, no matter how 'awful' it is. ;)

Edit: I just remembered I had this site bookmarked. It has a listing of a bunch of Android dev resources, but I haven't had the time to personally check all of them for usefulness.
 

upandaway

Member
Hi Programming-GAF,

I want to build a better programming portfolio than just school projects that I have from college and the first thing that came to my mind was MP3 player. I don't know where to begin and what language would be best for a MP3 player. Preferably, I would want to work with Java. I also don't have any experience with GUI other than working with front-end HTML/CSS so it will be entirely new to me. Can someone point in the right direction to get started on such a project?

Thanks :)
If you want Java, you could do it all pretty easily with Java 7 (JavaFX for GUI and Media/MediaPlayer). For outside libraries with Java 6, JLayer and mp3transform are pretty fancy.
Even I managed a neat GUI with JavaFX, so it requires zero anything.
 

Exuro

Member
Could someone that has experience with making a shell give me some pointers? I'm making one that can redirect with <, >, and >>, can pipe with | and can put commands in the background with &. I've already figured out the background process and redirection but after going over my code I'm not sure if my design is "proper". Right now I'm tweaking around with where my parsing is performed and after a while I'm still not sure how I should go about it.

My main steps right now are to parse the input string into a linked list(parsed by spaces) in main, and then in a separate function(I'll need this for recursion when piping) I forked and then parse the linked list, checking for redirection, pipes, & in the child and doing whatever. After looking over it I'm not sure if I should do it all in the child or do the second parsing somewhere else. I'm messing around with doing the second parsing before I fork but then I realized if I found an error in the list then I couldn't simply error and exit since I haven't forked to the child. Then I thought maybe I could go with it and just not exit and instead if i hit an error to stop the parse loop, skip the fork and go back to input.

Hopefully someone understand what I'm talking about.
 

Slavik81

Member
Hey guys! A follow up to my previous post, but where should friend functions be written out? If I try to insert it in the header file of my class, the compiler brings up an error, but in my implementation cpp file, it seems to compile correctly. What's the general practice when dealing with friend functions?
Non-member friend functions are coupled to the class like members are and should probably be in the implementation file with all the members.

Though, the error you saw was not related to the use of friend. All functions defined in a header should be marked as inline to prevent link errors when it's discovered to have been included in multiple object files (by its header being #included into multiple cpp files).
 

oxrock

Gravity is a myth, the Earth SUCKS!
Blah blah blah, programming woes. I figured it out and now feel ashamed of this massive wall of text :p

Pretty picture of my game thus far:
reSBdRZ.jpg
 

sdijoseph

Member
Does anyone know if it's even possible to get a computer science related internship after only 1 year experience in learning programming? I am in the middle of my second semester of learning C++ (the class I am in now concerns data structures), and I am wondering if I have enough experience for any type of paid internship in the CS area.

For reference, my entire knowledge of programming comes from these two courses:

CMPSC 121
CMPSC 122 (The one I am taking now)

Also, I live in the Greater Philadelphia area.
 
Could someone please tell me why this code is not working?
Code:
- (void)orientationDidChanged: (NSNotification *)notification {
    UIDeviceOrientation devOrientation = [UIDevice currentDevice].orientation;
    
    if (UIDeviceOrientationIsLandscape(devOrientation)) {
        UIStoryboard *main = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
        
        HorizontalController *horizontal = [main instantiateViewControllerWithIdentifier:@"horizontal"];
        
        [B][self presentViewController:horizontal animated:YES completion:nil];[/B]
    } else if (UIDeviceOrientationIsPortrait(devOrientation)) {
        [self dismissViewControllerAnimated:YES completion:nil];
    }
}

The error is
Incompatible pointer types sending 'HorizontalController *' to parameter of type 'UIViewController *'

I am following this tutorial.
 

Linkhero1

Member
If you want Java, you could do it all pretty easily with Java 7 (JavaFX for GUI and Media/MediaPlayer). For outside libraries with Java 6, JLayer and mp3transform are pretty fancy.
Even I managed a neat GUI with JavaFX, so it requires zero anything.
Is JavaFX a library or built in Java SDK?
 

harSon

Banned
I'm in need of some help. I'm trying to calculate Pi using the Liebniz Series.

6c17e102a2b48bd9d01dcbb77985ac67.png


Here's what I have so far:
Code:
#include <iostream>
#include <math.h>
#include <iomanip>

using namespace std;
int main()
{
    const int MAX_ITERATION = 21;
    double sum, totalSum;
    double x = 3.0;
    double y = 0.0;

    for (int i = 0; i < MAX_ITERATION; i++, x+=2, y+=1)
    {

        if (i % 2 == 0)
        {
            sum -= (1.0/(x * pow(3,y)));
        }
        else
        {
            sum += (1.0/(x * pow(3,y)));
        }
    }

    totalSum = sqrt(12) * (1 - sum);

    cout << totalSum << endl;
}

I'm using a for loop to do it, and the nested if loop is supposed to alternate between adding and subtracting. I've been trying to get this to work for a while now. I get 2.49657 which obviously isn't right. Could someone give me a nudge in the right direction? Just a hint please, I'd like to tackle this primarily on my own merits... but I've hit a road block atm.
 

tokkun

Member
You guys may find this interesting. The source code containing Apple's SSL bug was brought to light.
http://www.imore.com/understanding-apples-ssl-tls-bug

Code:
static OSStatus
SSLVerifySignedServerKeyExchange(SSLContext *ctx, bool isRsa, SSLBuffer     signedParams,
                             uint8_t *signature, UInt16 signatureLen)
{
    OSStatus        err;
    ...

    if ((err = SSLHashSHA1.update(&hashCtx, &serverRandom)) != 0)
        goto fail;
    if ((err = SSLHashSHA1.update(&hashCtx, &signedParams)) != 0)
[B]        goto fail;
        goto fail;[/B]
    if ((err = SSLHashSHA1.final(&hashCtx, &hashOut)) != 0)
        goto fail;
    ...

fail:
    SSLFreeBuffer(&signedHashes);
    SSLFreeBuffer(&hashCtx);
    return err;
}

Coding style issues aside, it's really surprising to see how lax Apple's policies must be to let that sort of bug get into production. It could have easily been caught in code review. It could have been caught with static code coverage analysis. It should have been caught with unit tests. It should have been caught with integration tests. It should have been caught by a security audit. Really baffling.
 

Magni

Member
You guys may find this interesting. The source code containing Apple's SSL bug was brought to light.
http://www.imore.com/understanding-apples-ssl-tls-bug

Code:
static OSStatus
SSLVerifySignedServerKeyExchange(SSLContext *ctx, bool isRsa, SSLBuffer     signedParams,
                             uint8_t *signature, UInt16 signatureLen)
{
    OSStatus        err;
    ...

    if ((err = SSLHashSHA1.update(&hashCtx, &serverRandom)) != 0)
        goto fail;
    if ((err = SSLHashSHA1.update(&hashCtx, &signedParams)) != 0)
[B]        goto fail;
        goto fail;[/B]
    if ((err = SSLHashSHA1.final(&hashCtx, &hashOut)) != 0)
        goto fail;
    ...

fail:
    SSLFreeBuffer(&signedHashes);
    SSLFreeBuffer(&hashCtx);
    return err;
}

Coding style issues aside, it's really surprising to see how lax Apple's policies must be to let that sort of bug get into production. It could have easily been caught in code review. It could have been caught with static code coverage analysis. It should have been caught with unit tests. It should have been caught with integration tests. It should have been caught by a security audit. Really baffling.

Wow yeah that's pretty bad :lol

Waiting for my OS X update here...
 

Tristam

Member
Any Qt users in here? Would love some advice!

I started developing a GUI app with a fairly straightforward structure. The main workspace consists of QWidget objects (each with their own set of basic widgets on them, like line edits, comboboxes, etc.) embedded on QTabWidget tabs. Navigation is supplemented by a QTreeWidget object that acts as a tab browser/explorer. The signals and slots are connected in a way that clicking on any item in the tree widget will activate the item's corresponding tab. To achieve this, I set each tab's widget as each corresponding tree widget item's data by using the QTreeWidgetItem class's setData method.

There's more to it, of course, but that's the crux of it. I'm seeking advice with respect to writing to and reading from disk. Although I'm toying with other methods, my initial inclination is to save in binary format via a QDataStream object. Unfortunately, objects subclassed directly from QWidget can't themselves be written to the stream. So, prior to writing each tree widget item, I need to write to the stream each QWidget object's component widgets (line edits, comboboxes, etc.), then reset the tree item's data to strip out the QWidget object, and finally write the tree widget item itself (the class of which has its own read/write methods to read from/write to a binary data stream). Of course, when I then read that data in, I've got a mass of unstructured data, and to re-structure (and, in essence, re-create) the file I more or less need to call my own custom tree-item/tab pair creation methods (which are used for creating tree-item/tab pairs outside of just reading/writing to disk) on each tree item that is read in.

Am I approaching this the right way? (I mean, I gave it a few cursory tests before going to bed last night, and it works, but it *feels* like a workaround hack, and I strive for something better than merely functioning, and since I was just toying around with this yesterday I haven't yet gotten the chance to see how long the read/write operations would take on a file heftier than a mere 20k.) Note that I'm using a Python binding for Qt, but that ought to be irrelevant for this.

So, an update to this...I now have my model and view completely segregated. (Thanks again, Slavik, for your suggestion--everything is much cleaner now, and I feel I have much more control over things now that I have my own custom tree model subclassed from QAbstractItemModel.) As a result, serializing the data is a more straightforward task because accessing the data is itself a more straightforward task, but my high-level approach to serialization/de-serialization remains quite similar: that is, I write in data of standard types (string, int, float, etc.), by simply looping over a list of each tree node object's attributes, and when I read that back in, the data will naturally be in a raw state: merely invoking a shift operator (or using some type-specific Qt built-in like readString() or readFloat() on the stream object) will of course do nothing to re-create the saved file's objects or model structure, so I call the appropriate methods to place that data back in object containers and in the data model. It no longer feels hack-ish at all, but just to be sure, is that an appropriate general approach for serializing/de-serializing data in a typical desktop program?

My Qt/PyQt/PySide primer until now has mostly been Mark Summerfield's Rapid GUI Programming with Python and Qt; the author dedicates one chapter to loading and saving data, and the approach he takes is essentially similar--it just looks much simpler because he's only writing to and reading from a table model, and doing so is naturally a much cleaner task than writing to and reading from a variable-column tree model. Other examples I see (e.g., in Qt's own documentation) are extremely simplified.
 

Slavik81

Member
When serializing data you have a few options. The main ones are binary vs textual, and ordered vs key-value pairs. I can speak to some of the tradeoffs, though I don't promise an exhaustive list.

Text files are slower to parse, but easy to read and edit. They're easy to use cross-platform too, since text is almost universally compatible (line endings aside).

Binary files may be faster because you can just directly load them, but there are gotchas like sizeof(int) or other types differing between platforms, or big-endian vs little-endian byte ordering. If you want cross-platform files, some extra code is required.

Binary files may seem at first to be smaller and more consise, but it should be noted that text compresses very well. Binary is not always more consise, either. A cool property of textual notation is that smaller numbers take less space than big numbers. In ascii, 1 can be represented with 1 byte, while 100 takes 3. Binary tends to be fixed width, so textual can occasionally win surprise victories if the data is right.

Of course, if you need random access, you probably want a binary file. As mentioned, text data is variable width so you can't seek to a field without reading all previous fields (or alternatively, reading an index, but maintaining an index would be annoying for a text file).

On the other dichotomy, ordered fields have the advantage that you don't need to save the field keys to the file, thus saving space. Unfortunately, this also makes it difficult to edit the file as nothing is labelled in it. Extending the format is also a little unwieldy. The easiest way to do it is to just increment the format version number and tack more fields on the end. Otherwise your code starts filling up with if (version > x) every few lines, though whether you prefer a lack of logical ordering in the file or a pile of ifs is up to you.

Key value pairs are certainly simpler. When editing, everything is labeled and you can just treat every field individually. If you end up not finding a field, you either use a default or throw an error.

Typically, text files are key-value pairs, and binary files are ordered, but ordered text files or key-value binary files are certainly possible.

background is just a .jpg i found searching on google, nothing special.
You have an appropriate tag. Also, it's impressive what a difference a nice background makes.
 
JavaFX is freaking great for rapid visual prototypes. I really loved the time spent with it. No idea how much it has changed since I used it 3-4 years ago though. I remember some new feature being added right when I actually needed it.

In contrast, I really damn hated working with GUIs on Java. I felt that I was writing at least twice the amount of code for something that looks ugly anyway.
 

leroidys

Member
You guys may find this interesting. The source code containing Apple's SSL bug was brought to light.
http://www.imore.com/understanding-apples-ssl-tls-bug

Code:
static OSStatus
SSLVerifySignedServerKeyExchange(SSLContext *ctx, bool isRsa, SSLBuffer     signedParams,
                             uint8_t *signature, UInt16 signatureLen)
{
    OSStatus        err;
    ...

    if ((err = SSLHashSHA1.update(&hashCtx, &serverRandom)) != 0)
        goto fail;
    if ((err = SSLHashSHA1.update(&hashCtx, &signedParams)) != 0)
[B]        goto fail;
        goto fail;[/B]
    if ((err = SSLHashSHA1.final(&hashCtx, &hashOut)) != 0)
        goto fail;
    ...

fail:
    SSLFreeBuffer(&signedHashes);
    SSLFreeBuffer(&hashCtx);
    return err;
}

Coding style issues aside, it's really surprising to see how lax Apple's policies must be to let that sort of bug get into production. It could have easily been caught in code review. It could have been caught with static code coverage analysis. It should have been caught with unit tests. It should have been caught with integration tests. It should have been caught by a security audit. Really baffling.
I know it's not preferred style, but this is why I always use braces.
 

leroidys

Member
I'm in need of some help. I'm trying to calculate Pi using the Liebniz Series.

6c17e102a2b48bd9d01dcbb77985ac67.png


Here's what I have so far:
Code:
#include <iostream>
#include <math.h>
#include <iomanip>

using namespace std;
int main()
{
    const int MAX_ITERATION = 21;
    double sum, totalSum;
    double x = 3.0;
    double y = 0.0;

    for (int i = 0; i < MAX_ITERATION; i++, x+=2, y+=1)
    {

        if (i % 2 == 0)
        {
            sum -= (1.0/(x * pow(3,y)));
        }
        else
        {
            sum += (1.0/(x * pow(3,y)));
        }
    }

    totalSum = sqrt(12) * (1 - sum);

    cout << totalSum << endl;
}

I'm using a for loop to do it, and the nested if loop is supposed to alternate between adding and subtracting. I've been trying to get this to work for a while now. I get 2.49657 which obviously isn't right. Could someone give me a nudge in the right direction? Just a hint please, I'd like to tackle this primarily on my own merits... but I've hit a road block atm.
Are you not initializing sum?
 

iapetus

Scary Euro Man
My experience has been that using single-line if/while/for expressions leads to bugs. You might be able to handle it, but in several large-scale projects with multiple developers I've seen a lot of bad errors as a result of doing that, and no corresponding errors from an excess of braces and whitespace. You don't even get RSI from it any more, as your IDE will put them in for you. :D

Like I said, we've got different stylistic preferences here, I suspect, and there's probably not a definitive 'right' way to do most of these things.

Okay, I take that back. I think Apple have shown us that there is a definitive 'right' way to do this - if they used braces even for single-line if statements then they wouldn't have a steaming great security hole across all their platforms right now.

They've also shown us a little something about the benefits of unit testing... I'll be bookmarking this bug for next time I find myself working for someone who wants us to skip testing to hit release dates.
 
Are you not initializing sum?

Just out of my head:

1. He has to initialize sum like you said (proper coding style)
2. If the formula works like that better check the value for y at the start. 3^0 = 1 not 3
3. The result calculation is wrong. You have to check if sum at the end is positive or negative

Edit: Easier in my eyes would be using a for-loop with sum = sum + pow(-1, i) / (2 * i + 1) from i = 0 to your desired iteration precision and then pi = 4 * sum
 

leroidys

Member
Not whose preferred style? It's certainly mine - for exactly this reason.

It's a style 9 c programming thing

https://developer.apple.com/library/mac/documentation/darwin/reference/manpages/man9/style.9.html

Space after keywords (if, while, for, return, switch). No braces are used for control statements with
zero or only a single statement unless that statement is more than a single line in which case they are
permitted. Forever loops are done with for's, not while's.

I think it's stupid.

1. He has to initialize sum like you said (proper coding style)

It's not just style, sum could contain any value if it's uninitialized.
 

Slavik81

Member
Okay, I take that back. I think Apple have shown us that there is a definitive 'right' way to do this - if they used braces even for single-line if statements then they wouldn't have a steaming great security hole across all their platforms right now.

They've also shown us a little something about the benefits of unit testing... I'll be bookmarking this bug for next time I find myself working for someone who wants us to skip testing to hit release dates.
Personally, I like Bumblebee as an example. Its consequences are more immediately understandable. It would have been caught by end to end acceptance tests on some of the projects I worked on (though admittedly, not all).
 

Tristam

Member
When serializing data you have a few options. The main ones are binary vs textual, and ordered vs key-value pairs. I can speak to some of the tradeoffs, though I don't promise an exhaustive list.

Text files are slower to parse, but easy to read and edit. They're easy to use cross-platform too, since text is almost universally compatible (line endings aside).

Binary files may be faster because you can just directly load them, but there are gotchas like sizeof(int) or other types differing between platforms, or big-endian vs little-endian byte ordering. If you want cross-platform files, some extra code is required.

Binary files may seem at first to be smaller and more consise, but it should be noted that text compresses very well. Binary is not always more consise, either. A cool property of textual notation is that smaller numbers take less space than big numbers. In ascii, 1 can be represented with 1 byte, while 100 takes 3. Binary tends to be fixed width, so textual can occasionally win surprise victories if the data is right.

Of course, if you need random access, you probably want a binary file. As mentioned, text data is variable width so you can't seek to a field without reading all previous fields (or alternatively, reading an index, but maintaining an index would be annoying for a text file).

On the other dichotomy, ordered fields have the advantage that you don't need to save the field keys to the file, thus saving space. Unfortunately, this also makes it difficult to edit the file as nothing is labelled in it. Extending the format is also a little unwieldy. The easiest way to do it is to just increment the format version number and tack more fields on the end. Otherwise your code starts filling up with if (version > x) every few lines, though whether you prefer a lack of logical ordering in the file or a pile of ifs is up to you.

Key value pairs are certainly simpler. When editing, everything is labeled and you can just treat every field individually. If you end up not finding a field, you either use a default or throw an error.

Typically, text files are key-value pairs, and binary files are ordered, but ordered text files or key-value binary files are certainly possible.


You have an appropriate tag. Also, it's impressive what a difference a nice background makes.

Thanks again for your excellent help! I think the binary serialization gotchas that you mentioned is leading me towards a couple of other solutions: JSON (or XML) versus Python's pickle module (the language's default serialization module). The latter works so well because it can store arbitrary Python objects as a series of bytes, meaning (as I have my data structure set up, where each tree node contains a list of its child nodes) I literally need to do nothing more than dump the root node to the file that is being saved; reading in will be fairly easy as well. The only problem is that it apparently is insecure, and while these files would almost 100% certainly only being exchanged between trusted parties (i.e., a guarantee that no one is tampering with them), the fact that the files can be tampered with to run basically any shell command makes me extremely nervous.
 

Slavik81

Member
Are you not initializing sum?
I'm kinda surprised g++ says nothing even with -Wall -Wextra.

Valgrind easily catches these errors, though. It's not available for Windows, but it's a great tool for Linux developers.
Code:
#for Fedora / Red Hat
sudo yum install valgrind
#or for Ubuntu / Debian
sudo apt-get install valgrind
valgrind ./calcpi 
#or whatever you named your program
#instead of calcpi

You should have no errors. Any errors you do have, you should think long and hard about. If they represent purposeful behaviour by you or a library you use, you can write a suppression rule to ignore them. Otherwise, they should be fixed.
 
That's it, I'm selling my Apple stock.*



*I don't directly own Apple stock, but it's in the index funds in my 401K, and I'm not divesting of those, so I'm not actually selling any of my Apple stock.
 

Magni

Member

Granadier

Is currently on Stage 1: Denial regarding the service game future
That's it, I'm selling my Apple stock.*



*I don't directly own Apple stock, but it's in the index funds in my 401K, and I'm not divesting of those, so I'm not actually selling any of my Apple stock.

Read in Colbert's voice makes this so much better.
 

leroidys

Member
I'm kinda surprised g++ says nothing even with -Wall -Wextra.

Valgrind easily catches these errors, though. It's not available for Windows, but it's a great tool for Linux developers.
Code:
#for Fedora / Red Hat
sudo yum install valgrind
#or for Ubuntu / Debian
sudo apt-get install valgrind
valgrind ./calcpi 
#or whatever you named your program
#instead of calcpi

You should have no errors. Any errors you do have, you should think long and hard about. If they represent purposeful behaviour by you or a library you use, you can write a suppression rule to ignore them. Otherwise, they should be fixed.

I love valgrind. Catches a lot of stuff that gcc doesn't, and has some great memory profiling functionality.
 

Slavik81

Member
Why would you do a forever loop with a for? In terms of performance, it's the same as using a while, but semantically I'd argue that while is much more adapted to a forever loop than for is. Oh well, I don't work for Apple anyways.
I'll probably butcher the argument, because I don't agree with it, but some people like it because:
- a handful of compilers written during the heyday of the Roman Empire were not smart enough to implement while (true) as an unconditional jump, and checked if true was true every time. For, however, explicitly allows any of its statements to be null.
- they think a null conditional states more clearly that there is no condition under which the loop will terminate. The check against a constant is a thing, while a null statement is nothing.

Personally, I like while (true) because while is a simpler construct than for, and null statements are both uncommon and a little weird.

Thanks again for your excellent help! I think the binary serialization gotchas that you mentioned is leading me towards a couple of other solutions: JSON (or XML) versus Python's pickle module (the language's default serialization module). The latter works so well because it can store arbitrary Python objects as a series of bytes, meaning (as I have my data structure set up, where each tree node contains a list of its child nodes) I literally need to do nothing more than dump the root node to the file that is being saved; reading in will be fairly easy as well. The only problem is that it apparently is insecure, and while these files would almost 100% certainly only being exchanged between trusted parties (i.e., a guarantee that no one is tampering with them), the fact that the files can be tampered with to run basically any shell command makes me extremely nervous.

Just so you know, QDataStream itself handles the potential byte-ordering and sizeof differences I mentioned. If you follow the guidelines in its documentation, it should spit out cross-platform files. If you'd already implemented it with QDataStream and platform support was the reason you were switching, I hope I saved you a little work.
 

usea

Member
I also think while(true) makes more sense than for(;;) in general (I don't know details of C or C++). A for loop is a special type of while loop. If you're not going to use the extra bits of it, why not just go back to the base while loop instead of the special form?
 

oxrock

Gravity is a myth, the Earth SUCKS!
What did you end up doing to fix your animation issues?

Well the bullet animation was fixed when I figured out that I was improperly calling the update function that changed the bullet's y values.

As for everything else.... there was a LOT of learning and researching involved. I'm already a much better programmer than I was 2 days ago and this just makes me realize that I still have a ridiculously long way to go. But with 3 or so 16 hour days, this is what I produced. Not exactly time efficient but if I knew a couple days ago what I know now, I'm sure it'd of went much quicker.
 

Osiris

I permanently banned my 6 year old daughter from using the PS4 for mistakenly sending grief reports as it's too hard to watch or talk to her
Haha, Just saw this on Google+

Nice one JetBrains, gotta love them turning Apples mistake into a marketing opportunity :D

3V5Co97.jpg
 

Granadier

Is currently on Stage 1: Denial regarding the service game future
Well the bullet animation was fixed when I figured out that I was improperly calling the update function that changed the bullet's y values.

As for everything else.... there was a LOT of learning and researching involved. I'm already a much better programmer than I was 2 days ago and this just makes me realize that I still have a ridiculously long way to go. But with 3 or so 16 hour days, this is what I produced. Not exactly time efficient but if I knew a couple days ago what I know now, I'm sure it'd of went much quicker.

Damn, you need to turn that into 6, 8 hour days.
Congrats on your successfully running game though!

Nice one JetBrains, gotta love them turning Apples mistake into a marketing opportunity :D

Ouch.
 
Top Bottom