Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411672 Posts in 69398 Topics- by 58452 Members - Latest Member: homina

May 16, 2024, 04:53:49 PM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsDeveloperTechnical (Moderator: ThemsAllTook)ProgramGamer toys around in C++
Pages: 1 [2]
Print
Author Topic: ProgramGamer toys around in C++  (Read 3111 times)
oahda
Level 10
*****



View Profile
« Reply #20 on: August 20, 2015, 04:57:41 AM »

I don't know any language with a standard library or whatever that doesn't use radians for that. o:
Logged

ProgramGamer
Administrator
Level 10
******


aka Mireille


View Profile
« Reply #21 on: August 20, 2015, 10:31:09 AM »

Gml had variants for both, but the degree kinds were secondary. I guess I should just accept that degrees are useless by now...
Logged

powly
Level 4
****



View Profile WWW
« Reply #22 on: August 20, 2015, 01:41:34 PM »

CoolBasic has no support for radians whatsoever, even the sin and cos use degrees instead -- and the internal PI constant is, for some reason, not very precise (3.14159).

Not that it's a very relevant language.
Logged
oahda
Level 10
*****



View Profile
« Reply #23 on: August 21, 2015, 05:42:33 AM »

Gml had variants for both, but the degree kinds were secondary. I guess I should just accept that degrees are useless by now...
Nah, I use them for my engine. I know some people who'd scold me for that, tho.
Logged

Afinostux
Level 2
**

Forgotten Beats


View Profile
« Reply #24 on: August 30, 2015, 01:59:18 AM »

For C structs like what SDL uses, you can have them start zeroed really easily:

Code:
//this rect could be anything!
SDL_Rect shadyRect;

//this rect is at 0, 0, with width 0 and height 0
SDL_Rect zeroRect = {};

//this rect is at 2, 2, with width 64 and height 64
SDL_Rect definedRect = {2, 2, 64, 64};
Logged

TheLastBanana
Level 9
****



View Profile WWW
« Reply #25 on: August 30, 2015, 12:27:53 PM »

Yeah, globals in C++ cause all kinds of headaches. With my latest game/engine, I've been going out of my way to make sure everything is wrapped up in a class and to minimize static classes for exactly that reason.

It does mean you spend some extra time writing classes and have to keep references to them anywhere that you might need to access the data, but I find it's worth it to avoid the pain of debugging something that doesn't work because of globals that were initialized in an order you didn't expect, or not initialized at all, or not visible in certain files... the list goes on. Plus, it means you're forced to think about which classes actually need to access that data, which can be very helpful down the road design-wise.
Logged
oahda
Level 10
*****



View Profile
« Reply #26 on: August 30, 2015, 12:29:11 PM »

But every global is guaranteed to have been initialised before main() runs, at least, right?
Logged

Afinostux
Level 2
**

Forgotten Beats


View Profile
« Reply #27 on: August 30, 2015, 02:22:25 PM »

Sort of! C and C++ have very specific rules for how global values are stored. All global and static variables are stored in a pair of segments in the executable; one for initialized variables, and one for uninitialized. They're pretty much laid out exactly how they'll be in memory when the program runs, except the uninitialized variables have a count of the number of zeros they need instead of a value. I've got a book that explains it in a lot more detail, but that's the gist of it. so if you make some array of char doop[999999999] your executable will get larger by the size of the definition of the global variable, but the size of your running program in memory will get larger by 999999999 bytes.

My example earlier wasn't for globals, it was for variables allocated on the stack (ie. within a function without using 'new' or 'malloc' or whatever). Here's a more clear example:
Code:
struct dog {
   int fleas, hunger;
};

void dogStuff() {
   //fido is unknowable
   dog fido;
   //rover is without fleas or hunger
   dog rover = {};
   //peppy is a little itchy and hungry
   dog peppy = {1, 1};
}
Logged

TheLastBanana
Level 9
****



View Profile WWW
« Reply #28 on: August 31, 2015, 10:55:46 AM »

For the record, I was referring to ProgramGamer's earlier issues with globals, not your initialization example (I should have quoted the post). But yeah, the unintuitive nature of global initialization is what turns me off of them. I like to be able to lay out in code the exact order of initialization.
Logged
ProgramGamer
Administrator
Level 10
******


aka Mireille


View Profile
« Reply #29 on: August 31, 2015, 06:37:35 PM »

Huh, this turned into quite the interesting discussion. Thanks for the tip btw Afino, it's going to be useful!

Also, I'd like to hear more about globals and their initiation. Sounds like a fun topic to talk about in parties Wink
Logged

Afinostux
Level 2
**

Forgotten Beats


View Profile
« Reply #30 on: September 01, 2015, 03:18:02 AM »


sounds like a great party to me!
if you're interested, I know exactly why your program wouldn't compile when you divided everything up.

C and C++ programs are compiled into 'translation units', which are basically little tiny libraries that make up
a portion of a program. You can see this directly if you compile without linking, which will produce a number of
object files, which are functionally the same as a translation unit, as far as I am aware.
When you declare a global variable, the variable is global only to that translation unit. To be able to
see that global variable from another translation unit, it has to be able to see it through a link.

When you build an exe, the linker resolves links between the TUs to detemine how they 'see' one another.
The reason that your globals weren't working was actually because #include pastes the entire contents of a file
wherever it's written. So, for instance:

Code:
//highlander.h
#pragma once

int highlander;
int give_supreme_power();

Code:
//highlander.cpp
#include "highlander.h"

int give_supreme_power() {
   if (highlander == 0) {
      highlander = 1;
      return 1;
   }
   return 0;
}

Code:
//main.cpp
#include <cstdio>
#include "highlander.h"

int main() {
   if (!highlander) {
      printf("quickening highlander!\n");
      if (give_supreme_power()) {
         printf("OH YEAH\n");
         if (highlander) {
            printf("ROLL CREDITS\n");
         } else {
            printf("wait what\n");
         }
      } else {
         printf("huh, guess we already did that\n");
      }
   }
}

using msvc, that doesn't compile. "int highlander" is multiply defined, because that code is completely identical
to this:

Code:
//highlander.cpp
int highlander;
int give_supreme_power();

int give_supreme_power() {
   if (highlander == 0) {
      highlander = 1;
      return 1;
   }
   return 0;
}

Code:
//main.cpp
#include <cstdio>
int highlander;
int give_supreme_power();

int main() {
   if (!highlander) {
      printf("quickening highlander!\n");
      if (give_supreme_power()) {
         printf("OH YEAH\n");
         if (highlander) {
            printf("ROLL CREDITS\n");
         } else {
            printf("wait what\n");
         }
      } else {
         printf("huh, guess we already did that\n");
      }
   }
}

since #include is just dumbly pasting in. Obviously this can't work, because there can only be one highlander.
the extern keyword lets the linker know that it should find a global variable with the same name.  Just defining an extern variable isn't enough, just the same way that putting a phone number for a nonexistent pizza place into your local phone directory doesn't mean you can now order pizza, if you couldn't before.  The thing that the extern is linking to actually has to exist in exactly one of your source files.

So, this version of the example works:
Code:
//highlander.h
#pragma once

extern int highlander;
int give_supreme_power();

Code:
//highlander.cpp
#include "highlander.h"
int highlander;

int give_supreme_power() {
   if (highlander == 0) {
      highlander = 1;
      return 1;
   }
   return 0;
}

Code:
//main.cpp
#include <cstdio>
#include "highlander.h"

int main() {
   if (!highlander) {
      printf("quickening highlander!\n");
      if (give_supreme_power()) {
         printf("OH YEAH\n");
         if (highlander) {
            printf("ROLL CREDITS\n");
         } else {
            printf("wait what\n");
         }
      } else {
         printf("huh, guess we already did that\n");
      }
   }
}

And that should be that! that last one will compile.

As a bonus, you can see the global initialization rules in action in this program. Since we expect highlander to start as zero, all we have to do is name it.

All in all this kind of looks more like a C program than a C++ program with all those structs instead of classes with all public members. Might want to look into that. Also you're still seemingly putting everything into the same file altho you're no longer putting everything in the main function. Might want to split stuff up a bit? Learn how to do classes properly with a header and a source file? You generally put the class definition in a .h or .hpp header file and the implementation in a .cpp source file and then just include the header from where you need the class.

Using 'structs' or 'objects' to name your data structures has nothing to do with their 'object orientedness', it has to do with how their data is accessed. Really, both are identical in memory, it's just that all fields of a struct are public by default, and all fields of an object are private by default. Unless it's super duper important that access to a field be hidden, having to write a bunch of getters and setters to basic values is lots of typing for absolutely no gain. If everything in all of your objects is public anyway, calling them structs does nothing but save keystrokes.

Hope that helped in some way! There's a lot of stuff I wish someone had told me about C++ when I was starting out, so I'm happy to share. I mean, assuming you want to read all this gnarly gibberish Blink
Logged

oahda
Level 10
*****



View Profile
« Reply #31 on: September 02, 2015, 12:30:13 AM »

I know that, and I choose structs above classes (aren't objects instances of classes/structs rather than synonymous – why are you calling them objects?) sometimes for that very reason. I just meant the general practices which seemed a bit unusual compared to most C++ code I've ever seen or written. I really only gave it a quick glance tho, so I might have missed something.
Logged

Afinostux
Level 2
**

Forgotten Beats


View Profile
« Reply #32 on: September 02, 2015, 05:39:09 PM »

Right! Classes. Not objects. 3am typing ahoy.

I think that the goal of a practice project shouldn't be to learn general practice, it should be to learn the nuts and bolts of the language. The worst classes I ever had were the ones that treated dogma as the basics.
Logged

ProgramGamer
Administrator
Level 10
******


aka Mireille


View Profile
« Reply #33 on: September 02, 2015, 06:49:58 PM »

Oh hey I forgot to thank you for that really lengthy post you made about globals, so thanks!

And I agree, learn the intricacies of the language before you make up practices with it. Sounds like a no-brainer but it isn't for everyone hehe.
Logged

Afinostux
Level 2
**

Forgotten Beats


View Profile
« Reply #34 on: September 03, 2015, 12:45:56 AM »

No problem! I have free time and thick books Wink
Logged

oahda
Level 10
*****



View Profile
« Reply #35 on: September 03, 2015, 02:22:23 AM »

Yeah, I guess that's how I initially learned C++ and some other languages too.
Logged

Mariofan0
Level 0
***


Your Local Nintendo Fanatic


View Profile
« Reply #36 on: September 03, 2015, 02:38:10 AM »

Looking at the code, (Not really sure what it does mind you.) It looks like it may be fairly easy for me to learn, (Having had experience with GML the general premise doesn't look all too different.) I've got to ask though how viable would something created in C++ be in porting from PC to Console, Phones, and Tablets? I assume It'd be pretty ideal in that case, But I don't like to assume things. Another thing is does it require the knowledge of another programming language to function for game development? I assume there is more to it then just C++, but again I don't want to assume.
Logged

You wanted a signature? Boy I bet you're dissapointed.
oahda
Level 10
*****



View Profile
« Reply #37 on: September 03, 2015, 02:46:56 AM »

It is common to add a scripting language for somewhat bigger projects but it's absolutely not necessary and I've never done it until my most recent project.
Logged

JWki
Level 4
****


View Profile
« Reply #38 on: September 06, 2015, 11:19:49 AM »

To the issue of porting, C++ code is incredibly portable - if it's written to be from the very start. Compiler support for new C++ standards varies widely accross platforms, so new standard features have to be used with care, and there's details like endianness and data type sizes that have to be taken care of. However, much more important are the different performance characteristics of different platforms, it's very easy to write code that performs well on PC, but turns out to be a bottleneck on consoles due to smaller CPU memory caches, plus on some architectures you may have weak memory ordering which can invalidate the correctness of your program if you're making use of multithreading (which you should).
So portability of C++ code is much less an issue of the language itself but rather a question of code design and implementation, due to the low level nature of the language.
Logged
Pages: 1 [2]
Print
Jump to:  

Theme orange-lt created by panic