Gameboy Development Forum

Discussion about software development for the old-school Gameboys, ranging from the "Gray brick" to Gameboy Color
(Launched in 2008)

You are not logged in.

#1 2020-08-26 15:51:32

Shkire
New member
Registered: 2020-08-16
Posts: 2

OOP problem

Hi, I feel comfortable using OOP (I use it at work, C#) and I'm new using C.

That's why I'm trying to use a more OOP approximated option while programming on gbdk.

I've done a small test simulating a Human class.

I have 2 files, main and human:

human.c

Code:

#include <gb/gb.h>
#include <stdio.h>
#include <string.h>
struct HumanStruct
{
    char *country;
};

void SetAsSpanish(struct HumanStruct *const);

void SetAsEnglish(struct HumanStruct *const);

void SetAsFrench(struct HumanStruct *const);

void Speak(struct HumanStruct *const);


void SetAsSpanish(struct HumanStruct *const human)
{
    human->country = "spain";
}

void SetAsEnglish(struct HumanStruct *const human)
{
    human->country = "england";
}

void SetAsFrench(struct HumanStruct *const human)
{
    human->country = "france";
}

void Speak(struct HumanStruct *const this)
{
    if (strcmp(this->country, "spain") == 0)
    {
        printf("Hola");
    }
    else if (strcmp(this->country, "england") == 0)
    {
        printf("Hello");
    }
    else if (strcmp(this->country, "france") == 0)
    {
        printf("Bonjour");
    }
}

main.c

Code:

#include <gb/gb.h>
#include <stdio.h>
#include "human.c"

void main()
{
    struct HumanStruct Human spanish;
    SetAsSpanish(&spanish);

    struct HumanStruct Human english;
    SetAsEnglish(&english);

    struct HumanStruct Human french;
    SetAsFrench(&french);

    Speak(&spanish);

    delay(1000);

    printf("\n");

    Speak(&english);

    delay(1000);

    printf("\n");

    Speak(&french);
}

This work as expected, but when I try to use a human.h to define the human "public interface" I can make it work

human.h

Code:

typedef struct HumanStruct Human;

void SetAsSpanish(struct HumanStruct *const);

void SetAsEnglish(struct HumanStruct *const);

void SetAsFrench(struct HumanStruct *const);

void Speak(struct HumanStruct *const);

human.c

Code:

#include <gb/gb.h>
#include <stdio.h>
#include <string.h>
#include "human.h"

struct HumanStruct
{
    char *country;
};


void SetAsSpanish(struct HumanStruct *const human)
{
    human->country = "spain";
}

void SetAsEnglish(struct HumanStruct *const human)
{
    human->country = "england";
}

void SetAsFrench(struct HumanStruct *const human)
{
    human->country = "france";
}

void Speak(struct HumanStruct *const this)
{
    if (strcmp(this->country, "spain") == 0)
    {
        printf("Hola");
    }
    else if (strcmp(this->country, "england") == 0)
    {
        printf("Hello");
    }
    else if (strcmp(this->country, "france") == 0)
    {
        printf("Bonjour");
    }
}

main.c

Code:

#include <gb/gb.h>
#include <stdio.h>
#include "human.h"

void main()
{
    Human* spanish;
    SetAsSpanish(spanish);

    Human* english;
    SetAsEnglish(english);

    Human* french;
    SetAsFrench(french);

    Speak(spanish);

    delay(1000);

    printf("\n");

    Speak(english);

    delay(1000);

    printf("\n");

    Speak(french);
}

I can't get it compiled. What I'm doing wrong?

Thank you

Offline

 

#2 2020-08-26 21:10:46

AntonioND
Member
Registered: 2014-06-17
Posts: 134
Website

Re: OOP problem

If you post the error message maybe we will be able to help.

Offline

 

#3 2020-08-27 04:32:50

toxa
Member
Registered: 2020-02-13
Posts: 309

Re: OOP problem

this is invalid: void SetAsSpanish(struct HumanStruct *const); you can't have a parameter without a name unless it is a "..."

that approach you use is not an "object oriented", it's just a simple c-style api. neither of 3 key oop features are acheived here: incapsulation, inheritance, polymorphism. try google something like "object oriented C", for example this: https://www.cs.rit.edu/~ats/books/ooc.pdf

it is interesting to use oop with GB as a project itself, but not much help when you want to make a game or something, because you get rather slow and size-greedy code, while on game boy you are lacking both: speed and space.

also be sure, that you are using gbdk-2020.

Offline

 

#4 2020-09-01 15:31:52

bbbbbr
Member
Registered: 2019-03-04
Posts: 126

Re: OOP problem

Shkire,

If your game is not likely to be resource or processor speed constrained, then writing more efficient and compact code may not be as critical- yet they are still good habits to have on the platform.

Below are some links you might want to review if you have not already. Some of the material is dated and some might not apply anymore or as directly to GBDK (z88dk specifics). But overall resources such as these can start to give you an understanding of how to approach writing software on a system with limited resources, especially if you are coming from a higher level language and do not have much experience in the area. Things that are easy to take for granted when writing software on powerful modern hardware can have big consequences on these old platforms.

http://gbdk.sourceforge.net/guidelines.html
https://github.com/z88dk/z88dk/wiki/WritingOptimalCode

Others here may have suggestions for more recent and specific coding guidelines for working with GBDK and the Game Boy.

Best of luck on your projects!

Offline

 

#5 2020-09-01 17:31:46

toxa
Member
Registered: 2020-02-13
Posts: 309

Re: OOP problem

bbbbbr i won't suggest both of those links: the first one is too old and contains outdated info, the second one relates to z80 more than to gbz80. maybe someone should write a better guide that meets the recent SDCC features.

Offline

 

#6 2020-09-01 18:34:30

bbbbbr
Member
Registered: 2019-03-04
Posts: 126

Re: OOP problem

Perhaps you are tempted to write a guide? smile smile

In the absence of a better ones though, they still have useful information. Such as:

* Using global variables is generally more efficient that using local variables - (in other contexts use of global vars may be discouraged, but there are some speed and compactness benefits to using them more liberally in this environment)
* Avoid using multiplications, divisions and modulos as much as possible - (there are many small ways to minimize these- such as the item below)
* Compute things once and store the result - (look up tables/etc can improve speed and reduce code size)
* Avoid long lists of function parameters - (passing many parameters can add overhead, especially if the function is called often)
* Use types of appropriate size - (8 bit types will be more efficient and compact than 16 and 32 bit types)

Offline

 

#7 2020-09-01 18:54:27

toxa
Member
Registered: 2020-02-13
Posts: 309

Re: OOP problem

by your ##:
# yes, but it's better to use static variables than global
# avoid, if divider is not a power of 2. modern sdcc uses shifts and swap instruction nicely for optimization
# yes. that's common everywhere
# yes. also use inline functions if the function is short
# yes. also types may be promoted, some special C syntax kung-fu is required

also i might add:
# use profiling, look into generated asm, write several versions of a function to choose better (faster) one.
# don't forget const for arrays and structs with constant data - that reduces size of the rom significantly.
# use --max-allocs-per-node with some big values, like 50000; --opt-code-speed barely adds anything
# use latest SDCC builds from sdcc.sourceforge.net/snap.php i use #11845 it works very well and for now has all important fixes.
...
profit

Offline

 

#8 2020-09-04 19:43:58

AntonioND
Member
Registered: 2014-06-17
Posts: 134
Website

Re: OOP problem

Don't do loops over arrays of structs like this:

Code:

Enemy enemy[10];
for (i = 0; i < 10; i++)
{
    enemy[i].x = rand();
    enemy[i].y = rand();
}

Do them like this:

Code:

Enemy enemy[10];
Enemy *e = &(enemy[0]);
for (i = 0; i < 10; i++)
{
    e->x = rand();
    e->y = rand();
    e++;
}

This way it will just have to add the size of the struct rather than to multiply (current pointer = size of struct * current index).

Better yet, do this:

Code:

Enemy enemy[10];
Enemy *e = &(enemy[0]);
for (i = 10 - 1; i != 0; i--)
{
    e->x = rand();
    e->y = rand();
    e++;
}

It's faster to check if a variable is 0 than if it is equal to some other value.

Last edited by AntonioND (2020-09-04 19:44:54)

Offline

 

Board footer

Powered by PunBB
© Copyright 2002–2005 Rickard Andersson