• Advertisement
Sign in to follow this  

porting procedural c++ to oo syntax

This topic is 1223 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

as a design exercise, i've decided to try porting the procedural c++ code for my new collision maps API to oo syntax.

 

the procedural code is an array of structs, routines that operate on a single struct, and routines that operate on the array:

 

 

 

 
//  ################################## COLLISION MAPS ################################################
 
 
//   CM stands for collision map
 
#define CM_SIZE 300
 
#define CM_CACHE_SIZE 20
 
 
struct CMrec
{
int active,age,mx,mz,cx,cz,data[CM_SIZE][CM_SIZE];
};
 
CMrec CM[CM_CACHE_SIZE];
 
 
void clear_CM(int cache_index)
{
ZeroMemory(&CM[cache_index],sizeof(CMrec));
}
 
 
void clear_CM_cache()
{
int a;
for (a=0; a<CM_CACHE_SIZE; a++)
    {
    clear_CM(a);
    }
}
 
 
 
 
 
 
void add_to_CM(int i,int x,int z,int rad,int value)
{
int x1,z1,x2,z2,x3,z3;
x1=x-rad;
x2=x+rad;
z1=z-rad;
z2=z+rad;
for (x3=x1; x3<=x2; x3++)
    {
    for (z3=z1; z3<=z2; z3++)
        {
if (x3 < 0)
    {
    continue;
    }
if (z3 < 0)
    {
    continue;
    }
if (x3 >= CM_SIZE)
    {
    continue;
    }
if (z3 >= CM_SIZE)
    {
    continue;
    }
CM[i].data[x3][z3]=value;
        }
    }
}
 
 
 
 
 
 
void add_tree_plantmap_to_CM(int i,int mx,int mz,int px,int pz)
{
int a,x,z,cx,cz,x2,z2,rad,value;
//  a      loop counter
//  x,z    location of the plant in the map sq
//   cx,xz   is the index of the collsion map the plant is in
//  x2,z2 is the location of the plant in the collision map
//  rad is the radius of the plant
//  for each plant in map, if in CM, add to CM
//  value is the value written to the CM
for (a=0; a<maxplants; a++)
    {
//  calc plant x z
    x=px*plantmapsize+plant[a].x;
    z=pz*plantmapsize+plant[a].z;
    if (waterinway(mx,mz,x,z))
        {
        continue;
        }
    if (storepit_in_way(mx,mz,x,z))
        {
        continue;
        }
//  calc CM index cx,cz
//  if its not in this CM, skip the plant
    cx=x/CM_SIZE;
    if (cx != CM[i].cx)
        {
        continue;
        }
    cz=z/CM_SIZE;
    if (cz != CM[i].cz)
        {
        continue;
        }
//  ok, plant is in CM index cx,cz
//  add it to the CM
//  calc x,z coords in the CM (x2,z2)
    x2=x-cx*CM_SIZE;
    z2=z-cz*CM_SIZE;
//  set radius
    rad=3;
//  set value. 1 = tree
    value=1;
//  add it!
    add_to_CM(i,x2,z2,rad,value);
    }
}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
void add_savanna_tree_plantmap_to_CM(int i,int mx,int mz,int px,int pz)
{
int a,x,z,cx,cz,x2,z2,rad,value,mod;
//  a      loop counter
//  x,z    location of the plant in the map sq
//   cx,xz   is the index of the collsion map the plant is in
//  x2,z2 is the location of the plant in the collision map
//  rad is the radius of the plant
//  for each plant in map, if in CM, add to CM
//  value is the value written to the CM
//  mod is the modulo value for haw many trees to add
if (mz < mapsize/3)
    {
    mod=SAVANNA_TREE_MOD;
    }
else
    {
    mod=NON_TROPICAL_SAVANNA_TREE_MOD;
    }
for (a=0; a<maxplants; a++)
    {
    if (a%mod != 0)
        {
        continue;
        }
//  calc plant x z
    x=px*plantmapsize+plant[a].x;
    z=pz*plantmapsize+plant[a].z;
    if (waterinway(mx,mz,x,z))
        {
        continue;
        }
    if (storepit_in_way(mx,mz,x,z))
        {
        continue;
        }
//  calc CM index cx,cz
//  if its not in this CM, skip the plant
    cx=x/CM_SIZE;
    if (cx != CM[i].cx)
        {
        continue;
        }
    cz=z/CM_SIZE;
    if (cz != CM[i].cz)
        {
        continue;
        }
//  ok, plant is in CM index cx,cz
//  add it to the CM
//  calc x,z coords in the CM (x2,z2)
    x2=x-cx*CM_SIZE;
    z2=z-cz*CM_SIZE;
//  set radius
    rad=3;
//  set value. 1 = tree
    value=1;
//  add it!
    add_to_CM(i,x2,z2,rad,value);
    }
}
 
 
 
 
 
 
void add_rock_plantmap_to_CM(int i,int mx,int mz,int px,int pz)
{
int a,x,z,cx,cz,x2,z2,rad,value,dx,dz;
location L;
//  a      loop counter
//  x,z    location of the plant in the map sq
//   cx,xz   is the index of the collsion map the plant is in
//  x2,z2 is the location of the plant in the collision map
//  rad is the radius of the plant
//  for each plant in map, if in CM, add to CM
//  value is the value written to the CM
for (a=0; a<maxplants; a++)
    {
//  skip every other rock
    if (a%2 == 1)
        {
        continue;
        }
//  calc rock x z
    x=px*plantmapsize+plant3[a].x;
    z=pz*plantmapsize+plant3[a].z;
//  stuff it in a location...
    L.mx=mx;
    L.mz=mz;
    L.x=(float)x;
    L.z=(float)z;
//  check for other terrain in way of the rock
    if (terrain_in_way_of_rock(&L))
        {
        continue;
        }
    if (waterinway(mx,mz,x,z))
        {
        continue;
        }
//  calc CM index cx,cz
//  if its not in this CM, skip the rock
    cx=x/CM_SIZE;
    if (cx != CM[i].cx)
        {
        continue;
        }
    cz=z/CM_SIZE;
    if (cz != CM[i].cz)
        {
        continue;
        }
//  ok, rock is in CM index cx,cz
//  add it to the CM
//  calc x,z coords in the CM (x2,z2)
    x2=x-cx*CM_SIZE;
    z2=z-cz*CM_SIZE;
//  calc radius
//  calc dx and dz dimesions of bbox
    dx=(int)(plant3[a].v2.x-plant3[a].v1.x);
    dz=(int)(plant3[a].v2.z-plant3[a].v1.z);
//  divide by 2 to get x and z radii of bbox
    dx/=2;
    dz/=2;
//  rad = avg of x and z radii of bbox
    dx+=dz;
    dx/=2;
    rad=dx;
//  set value. 3 = rock
    value=3;
//  add it!
    add_to_CM(i,x2,z2,rad,value);
    }
}
 
 
 
 
 
 
 
 
 
void add_fruittree_plantmap_to_CM(int i,int mx,int mz,int px,int pz)
{
int a,x,z,cx,cz,x2,z2,rad,value;
//  a      loop counter
//  x,z    location of the plant in the map sq
//   cx,xz   is the index of the collsion map the plant is in
//  x2,z2 is the location of the plant in the collision map
//  rad is the radius of the plant
//  for each plant in map, if in CM, add to CM
//  value is the value written to the CM
for (a=0; a<maxplants; a++)
    {
//  calc plant x z
    x=px*plantmapsize+plant2[a].x;
    z=pz*plantmapsize+plant2[a].z;
    if (waterinway(mx,mz,x,z))
        {
        continue;
        }
    if (storepit_in_way(mx,mz,x,z))
        {
        continue;
        }
//  calc CM index cx,cz
//  if its not in this CM, skip the plant
    cx=x/CM_SIZE;
    if (cx != CM[i].cx)
        {
        continue;
        }
    cz=z/CM_SIZE;
    if (cz != CM[i].cz)
        {
        continue;
        }
//  ok, plant is in CM index cx,cz
//  add it to the CM
//  calc x,z coords in the CM (x2,z2)
    x2=x-cx*CM_SIZE;
    z2=z-cz*CM_SIZE;
//  set radius
    rad=2;
//  set value. 4 = fruit tree
    value=4;
//  add it!
    add_to_CM(i,x2,z2,rad,value);
    }
}
 
 
 
 
 
 
 
 
 
 
 
void add_trees_to_CM(int i,int mx,int mz,int cx,int cz)
{
int px1,pz1,px2,pz2,px3,pz3;
//  px1 etc are begin and end of loops for plant maps
//  px3 pz3      loop counters
px1=cx*CM_SIZE/plantmapsize;
px2=(cx+1)*CM_SIZE/plantmapsize;
pz1=cz*CM_SIZE/plantmapsize;
pz2=(cz+1)*CM_SIZE/plantmapsize;
for (px3=px1; px3<=px2; px3++)
    {
    for (pz3=pz1; pz3<=pz2; pz3++)
        {
//  add plant map mx mz px3 pz3
add_tree_plantmap_to_CM(i,mx,mz,px3,pz3);
        }
    }
}
 
 
 
 
 
 
 
 
 
void add_savanna_trees_to_CM(int i,int mx,int mz,int cx,int cz)
{
int px1,pz1,px2,pz2,px3,pz3;
//  px1 etc are begin and end of loops for plant maps
//  px3 pz3      loop counters
px1=cx*CM_SIZE/plantmapsize;
px2=(cx+1)*CM_SIZE/plantmapsize;
pz1=cz*CM_SIZE/plantmapsize;
pz2=(cz+1)*CM_SIZE/plantmapsize;
for (px3=px1; px3<=px2; px3++)
    {
    for (pz3=pz1; pz3<=pz2; pz3++)
        {
add_savanna_tree_plantmap_to_CM(i,mx,mz,px3,pz3);
        }
    }
}
 
 
 
 
 
 
 
 
void add_rocks_to_CM(int i,int mx,int mz,int cx,int cz)
{
int px1,pz1,px2,pz2,px3,pz3;
//  px1 etc are begin and end of loops for plant maps
//  px3 pz3      loop counters
px1=cx*CM_SIZE/plantmapsize;
px2=(cx+1)*CM_SIZE/plantmapsize;
pz1=cz*CM_SIZE/plantmapsize;
pz2=(cz+1)*CM_SIZE/plantmapsize;
for (px3=px1; px3<=px2; px3++)
    {
    for (pz3=pz1; pz3<=pz2; pz3++)
        {
//  add plant map mx mz px3 pz3
add_rock_plantmap_to_CM(i,mx,mz,px3,pz3);
        }
    }
}
 
 
 
 
 
 
 
 
void add_fruittrees_to_CM(int i,int mx,int mz,int cx,int cz)
{
int px1,pz1,px2,pz2,px3,pz3;
//  px1 etc are begin and end of loops for plant maps
//  px3 pz3      loop counters
px1=cx*CM_SIZE/plantmapsize;
px2=(cx+1)*CM_SIZE/plantmapsize;
pz1=cz*CM_SIZE/plantmapsize;
pz2=(cz+1)*CM_SIZE/plantmapsize;
for (px3=px1; px3<=px2; px3++)
    {
    for (pz3=pz1; pz3<=pz2; pz3++)
        {
//  add plant map mx mz px3 pz3
add_fruittree_plantmap_to_CM(i,mx,mz,px3,pz3);
        }
    }
}
 
 
 
 
 
 
 
void add_caves_to_CM(int i,int mx,int mz,int cx,int cz)
{
int num,a,index,cx2,cz2,x,z;
num=numcaves[mx][mz];
if (num < 1)
    {
    return;
    }
for (a=0; a<num; a++)
    {
    index=caveindex[mx][mz][a];
//  calc CM index of the cave
    cx2=crh2[index].x/CM_SIZE;
    cz2=crh2[index].z/CM_SIZE;
//  if cave not in this CM, skip the cave
    if (cx2 != cx)
        {
        continue;
        }
    if (cz2 != cz)
        {
        continue;
        }
//  cave is in this CM.
//  calc caves CM xz coords
    x=crh2[index].x-cx*CM_SIZE;
    z=crh2[index].z-cz*CM_SIZE;
//  rad=24      value=2 (cave)
    add_to_CM(i,x,z,24,2);
    }
}
 
    
 
 
 
 
 
 
 
void add_cavern_to_CM(int i,int cx,int cz)
{
int x,z,cx2,cz2;
//   calc CM of cavern (cx2 cz2)
cx2=cavern_x/CM_SIZE;
cz2=cavern_z/CM_SIZE;
//  if cavern CM is not this CM, return
if (cx != cx2)
    {
    return;
    }
if (cz != cz2)
    {
    return;
    }
//  calc x,z of cavern
x=cavern_x-cx*CM_SIZE;
z=cavern_z-cz*CM_SIZE;
//  5 = cavern   rad=40
add_to_CM(i,x,z,40,5);
}
 
 
 
void add_rockshelters_to_CM(int i,int mx,int mz,int cx,int cz)
{
int a,cx2,cz2,x,z;
for (a=60000; a<65000; a++)
    {
//  skip if different map sq
if (crh2[a].mx != mx)
    {
    continue;
    }
//  skip if different map sq
if (crh2[a].mz != mz)
    {
    continue;
    }
//  calc CM index (cx2,cz2) of rockshelter
cx2=crh2[a].x/CM_SIZE;
cz2=crh2[a].z/CM_SIZE;
//  skip if not in this CM
if (cx2 != cx)
    {
    continue;
    }
if (cz2 != cz)
    {
    continue;
    }
//  ok its in this CM
//  calc ccords
x=crh2[a].x-cx*CM_SIZE;
z=crh2[a].z-cz*CM_SIZE;
//  rad = 30    6 = rockshelter
add_to_CM(i,x,z,30,6);
//  clear the interior
add_to_CM(i,x,z-10,20,0);
    }
}
 
 
 
 
 
 
 
void add_volcano_to_CM(int i,int cx,int cz)
{
int x,z,cx2,cz2;
//   calc CM of volcano (cx2 cz2)
cx2=volcano_x/CM_SIZE;
cz2=volcano_z/CM_SIZE;
//  if cavern CM is not this CM, return
if (cx != cx2)
    {
    return;
    }
if (cz != cz2)
    {
    return;
    }
//  calc x,z of volcano
x=volcano_x-cx*CM_SIZE;
z=volcano_z-cz*CM_SIZE;
//  6 = volcano   rad=50
add_to_CM(i,x,z,50,6);
}
 
 
 
 
 
 
 
 
 
 
 
 
 
void add_huts_to_CM(int i,int mx,int mz,int cx,int cz)
{
int num,a,b,cx2,cz2,x,z;
num=numhuts3[mx][mz];
if (num < 1)
    {
    return;
    }
for (a=0; a<num; a++)
    {
    b=hutindex3[mx][mz][a];
    cx2=crh2[b].x/CM_SIZE;
    cz2=crh2[b].z/CM_SIZE;
    if (cx != cx2)
        {
        continue;
        }
    if (cz != cz2)
        {
        continue;
        }
    x=crh2[b].x-cx*CM_SIZE;
    z=crh2[b].z-cz*CM_SIZE;
//  7 = hut
    add_to_CM(i,x,z,10,7);
    }
}
 
 
 
 
 
 
 
 
 
 
void add_permshelters_to_CM(int i,int mx,int mz,int cx,int cz)
{
int a,x,z,cx2,cz2;
for (a=0; a<maxcavemen; a++)
    {
    if (!cm[a].active)
        {
        continue;
        }
    if (!cm[a].alive)
        {
        continue;
        }
    if (!cm[a].has_perm_shelter)
        {
        continue;
        }
    if (cm[a].shel_mx != mx)
        {
        continue;
        }
    if (cm[a].shel_mz != mz)
        {
        continue;
        }
    cx2=cm[a].shel_x/CM_SIZE;
    cz2=cm[a].shel_z/CM_SIZE;
    if (cx != cx2)
        {
        continue;
        }
    if (cz != cz2)
        {
        continue;
        }
    x=cm[a].shel_x-cx*CM_SIZE;
    z=cm[a].shel_z-cz*CM_SIZE;
//  8 = perm shel
    add_to_CM(i,x,z,10,8);
    }
}
 
 
 
 
 
 
 
 
void add_tempshelters_to_CM(int i,int mx,int mz,int cx,int cz)
{
int a,cx2,cz2,x,z;
for (a=0; a<max_world_objects; a++)
    {
    if (!worldobj[a].active)
        {
        continue;
        }
    if (!isshelter(a))
        {
        continue;
        }
    if (worldobj[a].mx != mx)
        {
        continue;
        }
    if (worldobj[a].mz != mz)
        {
        continue;
        }
    cx2=(int)worldobj[a].x/CM_SIZE;
    cz2=(int)worldobj[a].z/CM_SIZE;
    if (cx != cx2)
        {
        continue;
        }
    if (cz != cz2)
        {
        continue;
        }
    x=(int)worldobj[a].x-cx*CM_SIZE;
    z=(int)worldobj[a].z-cz*CM_SIZE;
//  9 = temp shelter
    add_to_CM(i,x,z,5,9);
    }
}
 
 
 
 
 
 
 
 
 
 
void gen_CM(int i,int mx,int mz,int cx,int cz)
{
//  clear the collision map
clear_CM(i);
//  helps if you make it active, etc! also - cx,cz must be set to add plantmaps (trees, rocks, fruit trees)!
CM[i].active=1;
CM[i].mx=mx;
CM[i].mz=mz;
CM[i].cx=cx;
CM[i].cz=cz;
//  add trees as required...
switch (map[mx][mz].coverage)
    {
    case WOODS:
        case JUNGLE:
            add_trees_to_CM(i,mx,mz,cx,cz);
            break;
        case SAVANNA:
            add_savanna_trees_to_CM(i,mx,mz,cx,cz);
            break;
        }
    add_caves_to_CM(i,mx,mz,cx,cz);
    if (map[mx][mz].rocks)
        {
        add_rocks_to_CM(i,mx,mz,cx,cz);
        }
    if (map[mx][mz].fruittree)
        {
        add_fruittrees_to_CM(i,mx,mz,cx,cz);
        }
    if (map[mx][mz].cavern)
        {
        add_cavern_to_CM(i,cx,cz);
        }
    add_rockshelters_to_CM(i,mx,mz,cx,cz);
    if (map[mx][mz].volcano)
        {
        add_volcano_to_CM(i,cx,cz);
        }
    add_huts_to_CM(i,mx,mz,cx,cz);
    add_permshelters_to_CM(i,mx,mz,cx,cz);
    add_tempshelters_to_CM(i,mx,mz,cx,cz);
    }
 
 
 
 
 
 
 
 
 
 
 
int get_CM_index(int mx,int mz,int cx,int cz)
{
int best,bestval,a;
//  first: see if it exists, if so return its index...
for (a=0; a<CM_CACHE_SIZE; a++)
    {
    if (!CM[a].active)
        {
        continue;
        }
    if (CM[a].mx != mx)
        {
        continue;
        }
    if (CM[a].mz != mz)
        {
        continue;
        }
    if (CM[a].cx != cx)
        {
        continue;
        }
    if (CM[a].cz != cz)
        {
        continue;
        }
    return(a);
    }
//  doesnt exist. need to make one.
//  serch for inactive, if found, use it to generate a CM and return its index...
for (a=0; a<CM_CACHE_SIZE; a++)
    {
    if (!CM[a].active)
        {
        gen_CM(a,mx,mz,cx,cz);
        return(a);
        }
    }
//  didnt find inactive CM. must use LRU one.
//  find LRU CM, use it to gen new CM, and return its index...
best=0;
bestval=0;
for (a=0; a<CM_CACHE_SIZE; a++)
    {
    if (CM[a].age > bestval)
        {
        best=a;
        bestval=CM[a].age;
        }
    }
gen_CM(best,mx,mz,cx,cz);
return(best);
}
 
 
 
 
 
 
 
//  age all maps except map i
void age_CMs(int i)
{
int a;
for (a=0; a<CM_CACHE_SIZE; a++)
    {
    if (!CM[a].active)
        {
        continue;
        }
    if (a == i)
        {
        CM[a].age=0;
        }
    else
        {
        CM[a].age++;
        }
    }
}
 
 
 
 
 
 
 
 
 
 
int CM_terrain_in_way(int mx,int mz,int x,int z,int rad)
{
int x1,z1,x2,z2,a,b,a2,b2,mx2,mz2,cx,cz,a3,b3,i;
//  x1 z1 z2 z2      start and end of loops 
//  a b    loop counters
//   mx2 mz2 a2 b2      normalized world coords
//  mx2 mz2 cx cz a3 b3     collsion map coords
//  i is the index of the collsion map
//  check for "off the map"
if (mx < 0)
    {
    return(1);
    }
if (mx >= mapsize)
    {
    return(1);
    }
if (mz < 0)
    {
    return(1);
    }
if (mz >= mapsize)
    {
    return(1);
    }
if (map[mx][mz].elevation == OCEAN)
    {
    return(1);
    }
if (map[mx][mz].elevation == IMPASSMTNS)
    {
    return(1);
    }
x1=x-rad;
z1=z-rad;
x2=x+rad;
z2=z+rad;
for (a=x1; a<=x2; a++)
    {
    for (b=z1; b<=z2; b++)
        {
mx2=mx;
mz2=mz;
a2=a;
b2=b;
//  normalize mx2 mz2 a2 b2
while (a2<0)
    {
    a2+=map_sq_size;
    mx2--;
    }
while (a2>=map_sq_size)
    {
    a2-=map_sq_size;
    mx2++;
    }
while (b2<0)
    {
    b2+=map_sq_size;
    mz2--;
    }
while (b2>=map_sq_size)
    {
    b2-=map_sq_size;
    mz2++;
    }
//  if off edge of world map, return -1    
if (mx2 < 0)
    {
    return(-1);
    }
if (mx2 >= mapsize)
    {
    return(-1);
    }
if (mz2 < 0)
    {
    return(-1);
    }
if (mz2 >= mapsize)
    {
    return(-1);
    }
//  convert to CM coords: mx2 mz2 cx cz a3 b3
cx=a2/CM_SIZE;
cz=b2/CM_SIZE;
a3=a2-cx*CM_SIZE;
b3=b2-cz*CM_SIZE;
//  get index of collsion map mx2 mz2 cx cz
i=get_CM_index(mx2,mz2,cx,cz);
age_CMs(i);
//  if cm[i].data[a3][b3] !=0, ret cm[i].data[a3][b3]
if (CM[i].data[a3][b3] != 0)
    {
    return(CM[i].data[a3][b3]);
    }
        }
    }
return(0);
}
 
 
 
 
 
 
 
 
//  ############################### END COLLISION MAPS ################################################
 
 

Share this post


Link to post
Share on other sites
Advertisement

continuing from previous post (mixing text and code doesn't work well for me for some reason).....

 

so the oo way:

 

a collision map struct + the methods that operate on a single struct would become a class. and the array of collision maps and the methods that operate on the array would become a second class.

 

but then i have a list of object pointers... not an array of structs...

 

so the entire array of structs and all the methods become a single class?

Share this post


Link to post
Share on other sites


but then i have a list of object pointers... not an array of structs...

 

I don't understand. What does this have to do with making your code more object-oriented?

 

I would do it piece by piece. For example, change CMrec to use the class keyword, but start out with everything public. Then maybe make clear_CM_cache call a clear() method on each element in CM instead of calling clear_CM for each index. As you move code into CMrec, you won't need every member to be public, so you can start making things private. Eventually, you'll have the syntax you want.

Share this post


Link to post
Share on other sites


I don't understand. What does this have to do with making your code more object-oriented?

 

it adds an extra dereference, so its not "exactly the same thing - but using oo syntax".

 

its more like an array of pointers to structs, than an array of structs.

Share this post


Link to post
Share on other sites

You don't need to put structs inside classes, the class itself serves as a place to group all the fields.

class CollisionMap {
  private: // or public, you should check each attribute
    int active,age,mx,mz,cx,cz,data[CM_SIZE][CM_SIZE];

  public:
    void add_tree_plantmap(int i,int mx,int mz,int px,int pz);
    // more public methods

  private:
    void add(int i,int x,int z,int rad,int value);
    // more private methods
}

If you have methods that work over a list of collision maps and those can't be placed somewhere else, it makes sense to create a class that is actually a list of collision maps, but it's highly tied to how you design your solution. There's not a single rule to follow, you'll know if it makes sense to create a class for something with some experience.

 

In this case, if you only have one method you could write:

class CollisionMapsList {
  private:
    std::vector<CollisionMap> maps;

  public:
    void age(int i);
}

or (if you want to still treat it like a vector a have a vector interface):

class CollisionMapsList : public std::vector<CollisionMap> {
  public:
    void age(int i);
}

But it looks like the vector of collision maps and the "age" method could be inside a bigger class (maybe inside a class "Field"? or "Level"?).

 

EDIT: Also, you should check all the parameters you use and your naming convention, it's really hard to understand what your code is doing.

Edited by DiegoSLTS

Share this post


Link to post
Share on other sites
What ApochPiQ said; you need to oop your design, not your syntax. What you're doing isn't so much of a port as a re-design. I don't mean to "be mean", but I'm gonna come off as such here: but do you really work for a pc gaming shop as in your tag line? I think back to all the places I put my resume in at and all the rejections I got due to some niggling corner of the c97 specification I missed and I gotta wonder how you got in with a game producer...

Share this post


Link to post
Share on other sites

but then i have a list of object pointers... not an array of structs...


Why? You can have an array of class _values_. This is perfectly legal:

class MyComplexClass { ... };

MyComplexClass array[100];
std::vector<MyComplexClass> vector;
OO as taught by Java schools (which have infected most C++ programmers, sadly) will indeed teach you to make a bunch of little objects with overly-specific functionality independent of larger systems. This is wrong. You can have a class that internally uses an array or vector to arrange its data. Both of the following are valid OO structures (in totally not-valid syntax), but one is fast and one is idiotic:

// Java-esque:
class Object {
  GetName();
  GetSize();
  DoStuff();
};

class ObjectManager {
  list of Object

  Object& GetObject(key);
};
// Better:
class ObjectManager {
  struct ObjectData {
    name;
    size;
    etc;
  };

  list of ObjectData;

  GetSize(Key);
  GetName(Key);
  DoStuffAll() { for each object: do stuff; }
}

Share this post


Link to post
Share on other sites

At minimum the sizing/placement code that appears repeatedly could be crushed down to a parent class object method.

 

Look for other common operations to be shared/inheritted

Share this post


Link to post
Share on other sites

OO as taught by Java schools (which have infected most C++ programmers, sadly) will indeed teach you to make a bunch of little objects with overly-specific functionality independent of larger systems. This is wrong. You can have a class that internally uses an array or vector to arrange its data. Both of the following are valid OO structures (in totally not-valid syntax), but one is fast and one is idiotic:


That's a little harsh.

OO as embodied by the original intent of the concept looks more like your first example than the second. The second one is more illustrative of Data Oriented Architecture which is a totally different beast again from OO.

Please don't conflate "different" with "one has to be wrong."

Share this post


Link to post
Share on other sites
The things that stand out for redesign in the OP are:

- There's a global (well, file-scope) variable which all of the functions are tightly coupled to. It would be cleaner to pass a CMRec reference to each function instead of the index. (or the entire array if you ever need to access more than one index in a function - I didn't thoroughly analyze it to see if that ever happened or not). If you are INTENTIONALLY using file scope for encapsulation, then this doesn't matter as much.

- There are a large number of parallel x,z operations which could become a lot cleaner to look at with a vector2 struct with some methods/operators.

- The numeric #defines should be changed to consts.

- Change C-style local variable declarations to C++ style define-with-initialization. Why? Keeping all variables in a good state at all times is a good idea, even if it is fairly minor in this case. ex:
 
int x1,z1,x2,z2,x3,z3;
x1=x-rad;
x2=x+rad;
z1=z-rad;
z2=z+rad;
->

int x1 = x-rad;
int x2 = x+rad;
int z1 = z-rad;
int z2 = z+rad;
You could put most of the functions as members of the CMRec struct, but you don't really have to. It's much more important to remove the dependence of those functions on that global CM array.

Overall, the code isn't really screaming "OOP me!" Just some minor tidying up and it would be fine. Edited by Nypyren

Share this post


Link to post
Share on other sites


Here's a quick effort at rewriting it to be a bit more 'OO', turning some globals into arguments and killing off pages of code duplication:

 

i like the way you rolled the three versions of "add_some_plantmap_to_collision_map" into one. i just did a quick and dirty copy/paste/edit to create the three routines quickly.

 

i notice that you put it all (the cache and maps) in one big class.

 

before checking the latest responses to this post, i was thinking that one would have 4 classes: a collision map class, a cache class (IE data type objects), and two type of "controller" objects (objects that contain primarily controller code and use two or more different data objects): a "collision checker" and a "collision map generator". the collision checker would use the cache and maps. the collision map generator would use a collision map, and the world map data structures.

 


That code could be a lot simpler (and more readable) if you took just a bit more care when writing it.

no doubt! note that the posted code is output from a code generator - the source script is not nearly as long (or as ugly).

 


As one who survived the "everything needs to become an object!" era, I've got somewhat of a different view of what "object oriented" means.

 

much of what you say brings back fond (and not so) memories for me! <g>.

 

usage pattern would indicate that an array of objects is desired. most usage is on an individual map. only searches and aging operate on the entire cache.

 


And as for the OP, where you are just trying to put things into little buckets because you think that is how others do it? That's an unnecessary modification to the code by itself. Make changes to add a feature or to remove a feature, or in modifications you do both, but don't just change things for the purpose of changing them alone. If it works, leave it alone.

 

as i said, design exercise only. the code in the game is still as originally posted. about the only thing i did was #define the magic numbers used to represent tree, rock etc. Note that in the original code posted, the value 7 is used for both volcano and something else (by accident - a BUG!).  however it has no effect, as collision checks are simply go/no go, and don't care what value is at the collision point (only that its non-zero).

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement