Java-Gaming.org    
Featured games (79)
games approved by the League of Dukes
Games in Showcase (477)
Games in Android Showcase (107)
games submitted by our members
Games in WIP (534)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Regarding pointers in Java  (Read 794 times)
0 Members and 1 Guest are viewing this topic.
Offline Oskuro

JGO Knight


Medals: 39
Exp: 6 years


Coding in Style


« Posted 2013-05-29 18:45:18 »

I'm having a bit of an organizational issue (read: a mess) in my code. Often objects within a data structure need to reference other objects from the same or other data structures. For example, a Player object might need to reference the Sprite object as well as the Level object.

So fair I've been using integers that point to globally accessible arrays containing all the items. This, of course, irks me, specially because of the many global arrays that need to be defined at compile time.

In C++ I'd go pointer crazy, having items hold a pointer, defined at runtime, to whatever item/structure I need.

As far as I understand it, technically an object instance in Java is a pointer, and, as such, assigning existing instances to inner pointers within the "child" objects would be a way to do this, right?

Example:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
// .... Parent Class

public class Parent
{
     private int childAllowance = 0;

     public void setAllowance(int value) { this.childAllowance = value; }
     public int   getAllowance()            { return this.childAllowance; }
}

// .... Global Array containing all the existing Parent Objects

public static Parent[] parentArray = new Item[]{ new Parent(), new Parent(), ... };

// .... Child Class

public class Child
{
     public Parent parent = null;

     public Child(Parent parent)
     {
          this.parent = parent;
      }

      public void getAllowance()
     {
           System.out.println("Obtains " +parent.getAllowance()+ " coin from Parent!");
      }
}

// ..... Main execution code

parentArray[x].setAllowance(10);

Child Jhonny = new Child(parentArray[x]);
Child Susie   = new Child(parentArray[x]);

Jhonny.getAllowance(); // "Obtains 10 coin from Parent!"
Susie.getAllowance(); // "Obtains 10 coin from Parent!"

parentArray[x].setAllowance(20);

Susie.getAllowance(); // "Obtains 20 coin from Parent!"
Jhonny.getAllowance(); // "Obtains 20 coin from Parent!"

Susie.parent.setAllowance(100);
Susie.getAllowance(); // "Obtains 100 coin from Parent!"
Jhonny.getAllowance(); // "Obtains 100 coin from Parent!"

System.out.println("Parent at X is giving " +parentArray[x].getAllowance()+ " coin to it's children"); // "Parent at X is giving 100 coin to it's children"


So this would result in both Child objects having a reference to the same Parent object held in the Array? Rather than making a clone, I mean, so if another part of the program modifies said object, the Child objects will see the change too.

And this, I guess, means that the object will not be lost as long as a reference exists, so the GC won't get crazy there.


Is this approach to have objects held in a centralized container class valid? Is there a massive caveat I'm not seeing? Because maintaining the array indices for the many objects is becoming a burden.

Offline Oskuro

JGO Knight


Medals: 39
Exp: 6 years


Coding in Style


« Reply #1 - Posted 2013-05-29 18:46:04 »

And yes, I am aware this is a sort of noobish java question.  Roll Eyes

Offline quew8

JGO Coder


Medals: 29



« Reply #2 - Posted 2013-05-29 19:08:44 »

That's why we have the noob sub-forum.

The answer I'm afraid to say is sort of. Java stores object instances as references (pointers sounded to much like C but that's what they are). So if you access an instance from a global store on two occasions, it will be the same instance.

HOWEVER if you pass that instance to a method or constructor then the value of the reference not the reference itself will be passed. It will be the same instance until you reassign it with an =. But it will remain the same instance in the scope from which the method / constructor was called.

I find it tends to just work and try not think of the horror that's going on under the hood.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
//Imagine a class Foo with a string field: name.

public static void main(String... args) {
    Foo f = new Foo("A Name");
    System.out.println("Pre Foobar: " + f.name);
    foobar(f);
    System.out.println("Post Foobar: " + f.name);

    Foo f2 = new Foo("A Name");
    System.out.println("Pre Foobar2: " + f.name);
    foobar2(f);
    System.out.println("Post Foobar2: " + f.name);

    Foo f3 = new Foo("A Name");
    System.out.println("Pre Foobar3: " + f.name);
    foobar3(f);
    System.out.println("Post Foobar3: " + f.name);
}

//Resets the field of the instance pointed to by the value of the reference passed to the method
public static void foobar(Foo f) {
    System.out.println("Start Foobar: " + f.name);
    f.name = "A Different Name";
    System.out.println("End Foobar: " + f.name);
}

//Resets the value of the reference passed to the method
public static void foobar2(Foo f) {
    System.out.println("Start Foobar2: " + f.name);
    f = new Foo("A Different Name");
    System.out.println("End Foobar2: " + f.name);
}

//Resets the value of the reference passed to the method
//Then
//Resets the field of the instance pointed to by the new value of the reference
public static void foobar3(Foo f) {
    System.out.println("Start Foobar3: " + f.name);
    f = new Foo("A Name");
    f.name = "A Different Name";
    System.out.println("End Foobar3: " + f.name);
}


The output for the above would be:

Pre Foobar: A Name
Start Foobar: A Name
End Foobar: A Different Name
Post Foobar: A Different Name

Pre Foobar2: A Name
Start Foobar2: A Name
End Foobar2: A Different Name
Post Foobar2: A Name

Pre Foobar3: A Name
Start Foobar3: A Name
End Foobar3: A Different Name
Post Foobar3: A Name

I hope this makes sense of it. If it doesn't keep reading it until it does. Have fun.

EDIT: Added complex but technically correct method descriptions. Don't you hate me now.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline ags1

JGO Ninja


Medals: 46
Projects: 2
Exp: 5 years


Make code not war!


« Reply #3 - Posted 2013-05-29 19:10:40 »

Why are you using arrays and not collections? For example, and ArrayList would wrap an array for you and take care of resizing and so forth. Then you could delegate to the collection class from specialized container classes that provide more specific get() and find() and select() methods specific to your application.

Offline 65K
« Reply #4 - Posted 2013-05-29 19:12:32 »

Object instances are, well, object instances and are accessed by pointers/references. By simply assigning references no new objects are created.

Neither is a centralized container class or some sort of object array good.

First, take a step back and identify the relationships that are really, really required.
For instance, if a Sprite is only for rendering a Player, then the Sprite might need to know the Player but not vice versa.
Objects that are only required for the duration of a method invocation could be passed as parameter as opposed to store them permanently as member variable.
Cyclic relationships are mostly evil and avoidable as are static global accesses.

Offline Oskuro

JGO Knight


Medals: 39
Exp: 6 years


Coding in Style


« Reply #5 - Posted 2013-05-29 19:28:13 »

My intention is to centralize re-usable resources.

For example, Sprite objects would be instantiated on level load, one for each sprite that can show up. The different entity objects would reference the same sprite when their draw() method is called.

In other words, one evil mushroom sprite object for n evil mushroom game entities.


This is a simplified example, but pretty much all my code is organized in the same fashion, trying to cling to a few notions of MVC design. As such, being able to quickly and efficiently reference objects from a remote collection is important.

The way I am implementing it right now, some decisions have to be made at compile time (say, if the graphics assets are being held in a publicly exposed collection part of a GraphicsManager class, then all classes using said assets need to be hardcoded to look for them in said class). The advantage to having direct references would be that there'd be no need to make such hard-coded calls, just feed the container reference to the constructor and have it set up the relationships.

I really hadn't considered using object instances as references mostly because I don't have a clear idea of when, in Java, object references are treated as such, or when they are "cloned".

Offline ags1

JGO Ninja


Medals: 46
Projects: 2
Exp: 5 years


Make code not war!


« Reply #6 - Posted 2013-05-29 19:44:03 »

Object references are always just the reference to an object. When you assign a new object to the reference, it is just containing a new address.

Nothing is ever 'cloned' unless you call a method to do that.

What I would do:

Have a collection object like SpriteLibrary that has a collection of all your sprites, perhaps as a map so you can access the sprites by name.

Then your individual objects get a reference to the sprite by calling spriteLibrary.get("poison_mushroom"). Then they will all be referencing the same instance of the sprites, because they can only get a reference to a sprite by calling the sprite library.

Of course, nothing in such a collection is ever going to get garbage collected because there is always a live reference to the SpriteLibrary, and from the SpriteLibrary to all the sprites. For sprites, that is probably desirable behavior, but for other cases you might want garbage collection to clean up.

Offline Oskuro

JGO Knight


Medals: 39
Exp: 6 years


Coding in Style


« Reply #7 - Posted 2013-05-29 19:49:50 »

That is what I am doing now (using an instance id to extract the object from a collection).

The problem remains that the Mushroom class needs to know where to look for its sprite.

Offline 65K
« Reply #8 - Posted 2013-05-29 19:50:10 »

For example, Sprite objects would be instantiated on level load, one for each sprite that can show up. The different entity objects would reference the same sprite when their draw() method is called.

This is a simplified example, but pretty much all my code is organized in the same fashion, trying to cling to a few notions of MVC design. As such, being able to quickly and efficiently reference objects from a remote collection is important.
For MVC analogies, it should be the other way round. Sprite is part of the view which knows the model/entity, but models do know nothing about view details.

The way I am implementing it right now, some decisions have to be made at compile time (say, if the graphics assets are being held in a publicly exposed collection part of a GraphicsManager class, then all classes using said assets need to be hardcoded to look for them in said class). The advantage to having direct references would be that there'd be no need to make such hard-coded calls, just feed the container reference to the constructor and have it set up the relationships.
Not sure if I understand that. Why not let the GraphicsManager create ready-to-use sprites with assigned assets, and thus prevent from exposing assets into the global space ? Call it GraphicsFactory/Builder/Whatever and you even have a name with a clearer meaning.


Offline ags1

JGO Ninja


Medals: 46
Projects: 2
Exp: 5 years


Make code not war!


« Reply #9 - Posted 2013-05-29 19:53:14 »

Where to find it? Not sure I get you. In my fantasy code, it might look like:

view.getSpriteLibrary().getSprite("poison_mushroom")

This kind of method access breaks the Law of Demeter, but I don't think its so bad. If you cared, you could do:

view.getSprite(...)

where the method on view delegates to SpriteLibrary.

And you would have a reference to view in any place you are drawing stuff on screen.

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Oskuro

JGO Knight


Medals: 39
Exp: 6 years


Coding in Style


« Reply #10 - Posted 2013-05-29 20:09:43 »

Not sure if I understand that. Why not let the GraphicsManager create ready-to-use sprites with assigned assets, and thus prevent from exposing assets into the global space ? Call it GraphicsFactory/Builder/Whatever and you even have a name with a clearer meaning.

Again, that's my approach. The problem comes when interfacing different modules. When Mr.Mushroom has to be drawn, the object itself does not contain the Sprite data, but rather needs to tell the Renderer to draw X sprite at so and so coordinates with so and so angle.

Right now, Mr.Mushroon has an ID stored, which the Renderer reads and uses to search the Sprite library.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
public static Renderer( "Mr.Mushroom! I need to draw you!" );

private Mr_Mushroom( "Sure thing! Here's my Sprite's Library ID!" ) { return sprite_id; }

public static Renderer( "Time to search! Now, who had the Sprites for Fungi?" )
{
   switch(MrMushroom.getType())
   {
      case Fungi:
        System.out.println("A-ha! To the FungiSpriteLibrary!");

        FungiSpriteLibrary.Search(sprite_id);
        break;
        // ....
   }
}

public static Renderer( "Found the Sprite! Time to draw! ") { draw(Sprite); }



My current train of thought is that, if Mr.Mushroom had a pointer to the actual Sprite object it is using, there'd be no need to search the collection, or even care who is holding the object, the Renderer could simply use the pointer to access the Sprite.

1  
2  
3  
4  
5  
public static Renderer( "Mr.Mushroom! I need to draw you!" );

private Mr_Mushroom( "Sure thing! Here's my Sprite!" ) { return this.Sprite; }

public static Renderer( "Thanks Mr.Mushroom! It's Drawing Time!") { draw(Sprite); }




Of course, learning about how Java handles object references is also a reason why I'm asking this. Don't want to turn this into a "solve this specific problem in my code" thread  Wink

@ags1 You posted your last reply as I was writing the silly code.

Offline ags1

JGO Ninja


Medals: 46
Projects: 2
Exp: 5 years


Make code not war!


« Reply #11 - Posted 2013-05-29 20:12:26 »

"My current train of thought is that, if Mr.Mushroom had a pointer to the actual Sprite object it is using, there'd be no need to search the collection, or even care who is holding the object, the Renderer could simply use the pointer to access the Sprite."

Exactly - that is why SpriteLibrary.getSprite() should return Sprite not int. Then everyone uses object references to the sprites in your sprite library.

Although I think I would just store the key - "poison_mushroom" in Mr Mushroom, then you can return different sprites from the library depending on other logic (like lighting or power-up). Rather than updating all your mushroom characters with a new sprite when such events occur.

Offline Oskuro

JGO Knight


Medals: 39
Exp: 6 years


Coding in Style


« Reply #12 - Posted 2013-05-30 10:43:34 »

I think I'm not explaining clearly what my problem is.

It is not how the Sprites are stored. It is how the Library is called.

In my current implementation, the Renderer class needs to know where to look for sprites, that is, it must have a reference to the Library object, which usually is hard-coded (yes, it could be defined at runtime, but it still means the Renderer and Library end up being linked to one another).

Furthermore, for each Render operation, the Library needs to be queried for it's contents.

I was thinking that, if each object had a pointer to the stored Sprite, then the intermediate steps of querying the library for the Sprite would not be needed, and, furthermore, as the Renderer would have no need to know about the Library, I could freely tinker with the Library itself without needing to worry about breaking the Renderer.

It also feels more "correct" from an OOP perspective to do this than to have hard-coded references to a globally accessible Library.


But we're quickly digressing here.


Offline actual

JGO Coder


Medals: 23



« Reply #13 - Posted 2013-05-30 11:43:41 »


Decoupling the Library from the Renderer is more important than the saving of the intermediate step. OOP does seek to de-emphasize the scope and use of global systems, so I think what you are trying to do is perfectly reasonable. A lot of times you end up with a System that manages a set of Child classes where all of the logic is in the System and the Child classes end up being little more than data containers. Often times you can push much of the System logic into the Child classes and have the Child classes more responsible for their own behavior. This is a more OOP approach, at least as outlined by David West's Object Thinking.

I did this with my Event system and I am much happier with the design. My Events were nothing but data containers and my Message System did all the work. This meant that every object that sent messages needed to know about the EventSystem itself in addition to the Events it wanted to send. After I refactored my design, the objects only had to know about the events they wanted to send, and the EventSystem was simplified to the point where I was able to get rid of it entirely and simply put Events in my queue of things that get updated every tick.


In your specific case, I think storing the Sprite in the object itself makes sense but there are some things to consider:

1. If there are a lot of objects of a given type that all use the same sprite, you are going to use some extra memory because each object will hold a reference to that sprite. It probably won't be a big deal, but it is something that might be important depending on how many objects you have on the screen at a time.

2. If you are not careful, you may make things more confusing, not less. Right now, your SpriteLibrary is coupled to your Renderer. You don't want your SpriteLibrary to be directly coupled to every concrete GameObject. If you have a base GameObject that everything inherits from, put the reference in there.

3. You may want to go even further and have the Game Object responsible for rendering itself. So the Renderer calls mrMushroom.render(x,y). This is in line with Behavioral OOP as described by David West in Object Thinking where the object is responsible for its own behavior.  How worth while this is depends on how complicated your rendering is.

Offline Danny02
« Reply #14 - Posted 2013-05-30 11:51:15 »

let me show you a clear seperated design

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
interface SpirteObject{ Position getPosition(); Sprite getSprite(); }

class MrMushroom implements SpirteObject{
  Sprite normal, powerMode;
  MrMushroom(Sprite normal, Sprite power, ...)
  Spirte getSprite(){ return isPowerMode() ? powerMode : normal;}  
  ...
}

interface SpriteFactory{ Sprite getSpriteOfFile(File f); } //somewhere there is an implementation which creates Sprites, nobody knows how maybe it is cached or not

class Game{
  List<SpirteObject> objects;
  Game(SpriteFactory sfactory){...}

  void createMrMushroom(){
     Sprite n = sfactory.getSpriteOfFile(MUSHROOM_NORMAL);
     Sprite p = sfactory.getSpriteOfFile(MUSHROOM_POWER);
     objects.add(new MrMushroom(n,p));
  }

  void render(){
    for(SpriteObject so : objects)
      drawSprite(so.getSprite, so.getPosition);
  }
}


Factorys are a great way to decouple your code, they hide from other code how to build objects.
Offline Oskuro

JGO Knight


Medals: 39
Exp: 6 years


Coding in Style


« Reply #15 - Posted 2013-05-30 18:20:09 »

Awesome, thanks! Got some reading to do....

Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

pw (35 views)
2014-07-24 01:59:36

Riven (33 views)
2014-07-23 21:16:32

Riven (21 views)
2014-07-23 21:07:15

Riven (24 views)
2014-07-23 20:56:16

ctomni231 (55 views)
2014-07-18 06:55:21

Zero Volt (47 views)
2014-07-17 23:47:54

danieldean (38 views)
2014-07-17 23:41:23

MustardPeter (43 views)
2014-07-16 23:30:00

Cero (59 views)
2014-07-16 00:42:17

Riven (56 views)
2014-07-14 18:02:53
HotSpot Options
by dleskov
2014-07-08 03:59:08

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:58:24

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:47:22

How do I start Java Game Development?
by ra4king
2014-05-17 11:13:37

HotSpot Options
by Roquen
2014-05-15 09:59:54

HotSpot Options
by Roquen
2014-05-06 15:03:10

Escape Analysis
by Roquen
2014-04-29 22:16:43

Experimental Toys
by Roquen
2014-04-28 13:24:22
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!