We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexProgramming Questions & HelpSyntax Questions › Object Copy... LITERAL
Page Index Toggle Pages: 1
Object Copy... LITERAL (Read 782 times)
Object Copy... LITERAL
Apr 10th, 2007, 5:26pm
 
Hi again everyone.
I've never been recognize for my writing skills, and i would kinda have a problem explaning what i have and what's my problem so:

http://img.photobucket.com/albums/v298/Decinoge/010-1.png

for a bigger view:
http://img.photobucket.com/albums/v298/Decinoge/011-1.png

so i have that Enemie factory, wich creates enemies on the biggining of a level. its cool. i have no problem with creating new random generated enemies, and making them verry independent. my problem however is, when i want to take them out of the FACTORY to the REAL world.

what happens is that it goes to the outer world cooly, but just for the first row of enemies. when an enemie dies, the object enemie and everything within, is LITERALY DISTROYED. BOOM, no more.

since what i do is a simple "world enemie = factory enemie", you can see where is the problem. it just copy's the adress, wich is actualy the same object. when one is destroyed, the other is also, so i can't make another copy of... nothing... something that's been destroyed.

the Java's thingie .clone(), is not an alternative aswell. too much objects, and i dont even imagine how i could make that.

another thing that i came up too was this link:
http://www.javaworld.com/javaworld/javatips/jw-javatip76.html?page=2

and a few others, that i dont understand :\
this is my first project with processing, and i'm not an experienced coder. the code on that link gives me a problem wich i cannot resolve, and some other codes that i've tryed from other links aswell.

however one thing i understood. for an exact copy of an object, we have to turn it into bytes, and copy those to a new place in memory. a friend of mine said that C has a memcpy() function that does that already. but not java.

so what have we come to?
i would realy apreciate a help with this problem. i dont know how convert an object in bytes, or even switch it back.
plus, i see a great advantage in making them bytes, cause then i would store the bytes on the factory, and not the object itself. when asked for a new enemie, the factory would convert the bytes in object, and put them in the WORLD.

this is a _bitchy_ problem that i came to, i any help would be apreciated. (actualy i dont even know how to ask it properly :\)

anyway, thanks for everything, and for your time.

Re: Object Copy... LITERAL
Reply #1 - Apr 10th, 2007, 5:46pm
 
i think we need your code to see what's wrong ...

F
Re: Object Copy... LITERAL
Reply #2 - Apr 10th, 2007, 7:18pm
 
http://www.deci.blindado.net/loliness/showing/

i'm not verry... confortable showing this before the time cause :\ its basicly a mess.
i have dificulty to find walk thru my own code after a few days without looking at it.

anyway, everything happens on the "enemies" file.
the first class "enemie" is the enemie itself.
the second class "enemie_mng" is the factory.
the enemies are destroied on the "render" file, that detects if the enemie is outside of some boudrys.

anyway, thru all the mess i have there, the only thing important in there is the function newEnemie() inside the enemie_mng class. that function is called by the level class/file, and should be inputed with an int A (a random one within the previously generated numbed of type of enemies) and a float B (simple X position of th enemie, just to have diferent starting points).

what the function SHOULD DO find a clear spot inside the global enemies[] array (this is THE WORLD, the one that is updated by the render, and puts them into the "game") and copy  the A member from the  eStored[] enemie array inside the enemie_mng class.

this way i would have a level creating a limited number of enemie types, and lunching enemies just with that type, creating a thing that would be more easly recognicible as a LEVEL.

however, what we have inside the interation that looks for an empty spot for the enemie, does that problem that i have. just copy's the adress, so... it still refers to the enemie on the eStored[] array, inside the enemie_mng class. when i destroy the enemie on the enemies[] global array, it also destroys that one. in the end, i get no enemies to copy.

i dont know if i made myself understandable, i have my doubts about that, but in the end, i just want to be able to make copy's of a complex object, with objects withing. that the new object would be compleatly independent of the object that from wich he was copyed.

again, thanks for your time
Re: Object Copy... LITERAL
Reply #3 - Apr 10th, 2007, 8:10pm
 
So when you build your stored list of enemies at the beginning you are giving them all different initial conditions, right? And you want those initial conditions to be preserved for the next time you need a new enemy like that.

One thing you might want to consider is creating a different class for each set of initial conditions you want to use. So you'd have enemie, but the you'd extend enemie with enemieRed or enemieAgro or whatever you want to call your extra classes. Then you'd store the parameters for the initial conditions in each of those classes. Instead of storing a list and cloning one of the enemies in the list when you want a new one, you'd just construct a new enemie based on the type being asked for. But then you'd hand it back as an enemie so that the level asking for an enemie didn't have to keep a separate list for each enemie. It wouldn't even have to know how many enemie types there are, so long as they all had the same methods for updating and drawing and so forth.

Alternatively, you could put all of your initial condition code into the enemie class itself, keeping only one enemie class, but being guaranteed that every time you construct a new one it has slightly different initial conditions.

Probably you don't want to do either of those things because they would require a significant rewrite of your existing code, but I think they are the better way to go, rather than putting all the initialization code in one place and using all those switch statements that you use. It can become a real nightmare to maintain.

The other option is to implement some kind of cloning function for your enemie class so that you can get an independant copy of a particular instance of an enemie. You wouldn't have to follow the Java clone() spec, you'd just have to ensure that when you construct a new enemie you are able to intialize it with the values of the enemie being cloned.

As a simple example:

Code:

class A
{
private int a, b, c;

A(int _a, int _b, int _c)
{
a = _a;
b = _b;
c = _c;
}

A makeCopy()
{
A copy = new A(a, b, c);
return copy;
}
}

A anA = new A(1, 1, 1);
A anACopy = anA.makeCopy();


Because your enemie class has some of your own classes as data members, you'd just have to make sure that all of those classes support copying as well.
 

Re: Object Copy... LITERAL
Reply #4 - Apr 10th, 2007, 8:16pm
 
I think that having a bin of unused enemies is a bad idea. You have to check all the time if a bin still has enemies in before lanching them (I tried writing out the code that way and it just seemed like too much work). It's easier if you have a specific list of baddies you are going to launch.

To cope with your constant amount of bad guys, I would give each an id of where they are in the array and when they are destroyed or fly past then generate a new baddie. You know which slot to use because you placed a reminder for yourself on the baddie.

Like this:
Code:

Factory maker;
void setup(){
size(200, 200);
rectMode(CENTER);
smooth();
maker = new Factory(20, "001010001111100100100100101011111111111111111000000000000000001111110001001011000111111000001111100010011");
}
void draw(){
background(30, 50, 60);
maker.draw();
}
class Factory{
int playhead;
Baddie [] stack;
StringBuffer wavePattern;
Factory(int num, String wavePattern){
this.wavePattern = new StringBuffer(wavePattern);
playhead = 0;
stack = new Baddie[num];
for(int i = 0; i < stack.length; i++){
recycle(i);
}
}
void recycle(int id){
if(playhead < wavePattern.length()){
int type = -1;
switch(wavePattern.charAt(playhead)){
case '0':
type = 0;
break;
case '1':
type = 1;
break;
}
stack[id] = new Baddie(random(width), -20, type, id, this);
playhead++;
}
}
void draw(){
for(int i = 0; i < stack.length; i++){
stack[i].move();
stack[i].draw();
}
}
}

class Baddie{
float x, y, speed, size;
int type, id;
Baddie(float x, float y, int type, int id, Factory maker){
this.x = x;
this.y = y;
this.type = type;
this.id = id;
speed = random(1, 4);
size = random(10, 20);
}
void move(){
if(y-size*2 > height){
maker.recycle(id);
}
else {
this.y += speed;
this.x += random(-1, 1);
}
}
void draw(){
switch(type){
case 0:
ellipse(x, y, size, size);
break;
case 1:
rect(x, y, size, size);
break;
}
}
}


If you want to copy an object you have to generate a new object. Any objects inside it you have to generate as new as well. Then all of the primitives inside (int, String, float, etc.) you have to copy by assignment into all levels of the entirely new object.

Personally I can't think why you would want to copy your aliens from existing ones, that's like saying you haven't got some solid code that initialises them in the first place.
Re: Object Copy... LITERAL
Reply #5 - Apr 10th, 2007, 8:22pm
 
looks good so far ..

your problem is that you copy the pointers, when you say:

enemies[i] = eStored[A]

enemies[i]
and
eStored[A]

reference the same object, so if you alter enemies[i] then eStored[A] will get changed too.

what you need is a copy function so that objects in eStored stay unaltered:

Code:


// inside enemie class
 enemie copy ()
 {
     enemie tmp = new enemie();
     tmp.pX = width/2;
     tmp.pY = 10;
     tmp.colField = colField;
     tmp.LIFE = LIFE;
     tmp.hCheck = hCheck;
     tmp.hitCheck = hitCheck;
     tmp.sDraw = sDraw; // same problem
     tmp.motion = motion; // here you are running into the same problem again ... you probably want to have a fresh motion object here.
     tmp.motion.pX = width/2;
     tmp.motion.pY = 10;
     tmp.shootPlan = shootPlan; // same problem
     return tmp;
 }


i set motion.pX / pY to just have the object reappear on screen.

now, with the new copy function inside enemie class, you can do:

Code:

 void newEnemie(int A, float B)
 {
   for (int i = 0; i < enemies.length; i++)
   {
     if (enemies[i] == null)
     {
       enemies[i] = eStored[A].copy();  // YAY!
       enemies[i].motion.pX = B;
       break;
     }
   }
 }


i think you get the idea. can't really tell which parts of enemie need to be copied and which you want to start fresh with ...

game looks nice. i like that your graphics consist of simple shapes to build complex bodies.

F
Re: Object Copy... LITERAL
Reply #6 - Apr 10th, 2007, 8:23pm
 
oh, and you need a plain constructor:

Code:

enemie () {}


F
Re: Object Copy... LITERAL
Reply #7 - Apr 10th, 2007, 8:26pm
 
see .. little bit of code, lot's of replies. what a nice place our discourse is ..

F
Re: Object Copy... LITERAL
Reply #8 - Apr 10th, 2007, 9:06pm
 
It looks like we were all writing at the same time, too. Heh.
Re: Object Copy... LITERAL
Reply #9 - Apr 10th, 2007, 9:07pm
 
yeah great indeed. but i see i dont have an easy way to go thru this problem.

to what st33d said, i can only say no. i dont have a good way to see what are the conditions of each created enemie, because i dont create them from a list. at least not on the conventional way.

i use the "shots" verry much.
http://www.deci.blindado.net/loliness/
see on DOCS the... kind of documentation i made about the shots. its basicly a particle system, that have the uses that i want. the shot_mng class just inputs values on the shot class, so the class behaves in determined ways. the good about the shoot_mng class is that already stores the values of the shot we want to make. so if we say "newShot(...... whatever we want it to do and so on" we can have the same shooting everytime we say "shoot".

that way i can easly have the same movement for many enemies of same kind, i would only have to say "getShot"...
well actualy that can be a good way to do it.

however a problem maintains. the whole enemie drawing, the enemie shooting plan, and the enemie creation itself is RANDOM. compleatly from its core.

i create a new enemie (that make enemie) and the reason why i make new motion and whatever objects, is because they create themselfs in a random way.

for example, the drawing. you probably cant see it right because of the grey colors i've used on the enemies, but when you start a new enemie_draw object, the object itself creates a random drawing. if you start the applet a few times, you'll notice the enemies are never the same, and hardly similar. you can start the applet as many times as you want, you will always have diferent enemie drawing.

now even worst is the enemie shooting plan. it is again also diferent every time. every time you enitialize a new shooting plan, you just have to say it where the shooting points are positioned. you can see that the class constructor gets an array with the position of the shots, and an array of simple 0s and 1s. that is determined on the enemie's drawing class, when that one is made, it determines the postion of the shooting points, and how many diferent kinds of shooting plans we want for the groups of shooting points that i have. that ia made on the enemie drawing class, because that is where the points of the drawing are, and it determines the shooting points positions depending on the points of the drawing. the 0s and the 1s are only to say when "make a new plan" and "aplly the plan you alrady have". what that plan making class does is call the "newShot(..... whatever you want the shots to do" into each shooting point, depending on 0 it will only call on the plan existed, on 1 makes a new plan and applys. finaly the update calls the "shoot(NOW)" whenever the plan decides to.

this is all generated with randoms, wich are the carnI, carnF, carnB on the first file.

so, each object is verry VERRY unique :\
they all make diferent things to the enemie. i could easly make a new random enemie everytime i wanted a new enemie. thats what i had before. if you erase what's inside the newEnemie() function of the enemie_mng class, and copy this there:

for (int i = 0; i < enemies.length; i++)
   {
     if (enemies[i] == null)
     {
       getMove();
       tempDraw = new enemie_draw(carnI(255), carnI(255));
       tempPlan = new enemie_shots(tempDraw.getShootPs(), tempDraw.getPlan());
   
       enemies[i] = new enemie(tempDraw, tempMove, tempPlan, tempDraw.maximus);
       break;
     }
   }

you will get a compleatly new random enemie ever 10 or 20 frames. i dont want so much random. i want 9 random enemies, and i want to call them every time i want :\, thank you for the hel but thats not exactly what i have here.

as for the rest of the comments, i have the same problem, i would have to do a copy class for each object :\
i guess that's the only way. but still i cant stubornly think that there should be a better way to do it. those java  pages i found explain exactly my problem and they probably tell how i could solve it. if i knew how to implement their code, and if i understood what they say on the page.

i'll try to wait a bit more for diferent opinions and guesses, but otherwize, i'll just make the copy function inside every class, wich will b a major pain XD but its cool Tongue

thanks everyone for the wonderfull help, its good to see that people are actualy interested in help and discuss the problems.
Page Index Toggle Pages: 1