Java-Gaming.org    
Featured games (81)
games approved by the League of Dukes
Games in Showcase (495)
Games in Android Showcase (114)
games submitted by our members
Games in WIP (563)
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  
  Best Way to Register Blocks/Entities  (Read 3439 times)
0 Members and 1 Guest are viewing this topic.
Offline Slyth2727
« Posted 2014-01-18 18:22:03 »

Wow, it's been a while since I posted a question.

I finally re wrote my rendering system for my puzzle game that I restarted a while ago and I need a good way to register blocks. Here is what the game looks like so you can get a feel for what I have:



So there are blocks, but I need a way to register the different types. Eg, trampoline block, or normal wall block and so forth. Right now I am just creating a new instance of the class of that block which then registers a Box to jME. I then join all the meshes together at the end of building the current level. So performance isn't a problem.
What's the best way to approach it so that I can, in the level creation code, call:

1  
        makeBlock(new Vector3f(3, 40, 40), Block_Wall.class);


Therefore, creating the block of whichever block.class I put in there?
The constructor for the makeBlock is:

1  
2  
3  
4  
    public void makeBlock(Vector3f pos, Class<? extends BlockSuper> block){
        blocks[(int) pos.x][(int) pos.y][(int) pos.z] = new BlockSuper(main, new Vector3f(pos.x, pos.y, pos.z), level);
        blocks[(int) pos.x][(int) pos.y][(int) pos.z].setUpPhysics();
    }


So as you can see I just create a BlockSuper there, which is the superclass for all blocks. I need to take the .class of whatever block I want there and create an instance of it from that. I know about reflection:
1  
2  
3  
4  
5  
6  
7  
        try {
            Class<?> clazz = Class.forName("Engine.Blocks.BlockSuper");
            Constructor<?> constructor = clazz.getConstructor(Main.class, Vector3f.class, Node.class);
            Object instance = constructor.newInstance(main, pos, level);
        } catch(Exception e){
            e.printStackTrace();
        }


However I really don't know if this is what I should be using, as it is a rather new concept to me.
Thanks for any help.

Was I before Chuang Tzu who dreamt about being a butterfly, or am I now a butterfly who dreams about being Chuang Tzu?
Offline Danny02
« Reply #1 - Posted 2014-01-18 19:07:00 »

Why do you think that it is unfeasible to just "register" already build block instances?
Offline Slyth2727
« Reply #2 - Posted 2014-01-18 19:54:41 »

Could you elaborate?

Was I before Chuang Tzu who dreamt about being a butterfly, or am I now a butterfly who dreams about being Chuang Tzu?
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Danny02
« Reply #3 - Posted 2014-01-18 20:09:49 »

why not

1  
2  
3  
public void makeBlock(BlockSuper block) {...}

makeBlock(new BlockWall(main, new Vector3f(3, 40, 40)));
Offline Slyth2727
« Reply #4 - Posted 2014-01-18 20:49:44 »

Oh you're right... I was half asleep or something. Sometimes I get retarded like that. My bad.

Was I before Chuang Tzu who dreamt about being a butterfly, or am I now a butterfly who dreams about being Chuang Tzu?
Offline Slyth2727
« Reply #5 - Posted 2014-01-18 20:53:50 »

Oh you're right... I was half asleep or something. Sometimes I get retarded like that. My bad.


However, I do need to create walls and stuff. This is the wall creation code:
1  
2  
3  
4  
5  
6  
7  
8  
9  
    public void makeWall(Vector3f startPos, Vector3f endPos, Class<? extends BlockSuper> block) {
        for (int x = (int) startPos.x; x <= endPos.x; x++) {
            for (int y = (int) startPos.y; y <= endPos.y; y++) {
                for (int z = (int) startPos.z; z <= endPos.z; z++) {
                    makeBlock(x, y, z, block);
                }
            }
        }
    }


So just creating a new instance for that won't work.

Was I before Chuang Tzu who dreamt about being a butterfly, or am I now a butterfly who dreams about being Chuang Tzu?
Offline Danny02
« Reply #6 - Posted 2014-01-18 22:11:06 »

In this case you could use factories

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
interface BlockFactory<T extends BlockSuper>
{
  public T create(Vector3f pos);
}

public static final BlockFactory<WallBlock> wallBlockFactory = new BlockFactory<> {
  public WallBlock create(Vector3f pos){
    return new WallBlock(main, pos);
  }
}

makeWall(start, end, wallBlockFactory);
Offline Slyth2727
« Reply #7 - Posted 2014-01-18 22:58:16 »

Thanks Smiley

It would seem that factories are basically just things to create new objects of a class that extends another one, but you don't know which subclass it will be. Why not just use reflection? Please correct me if I'm wrong, I know next to nothing about factories.

Actually, I did some research and didn't find much on the subject. Would you mind giving a very brief explanation of them?


Was I before Chuang Tzu who dreamt about being a butterfly, or am I now a butterfly who dreams about being Chuang Tzu?
Offline ctomni231

JGO Wizard


Medals: 99
Projects: 1
Exp: 7 years


Not a glitch. Just have a lil' pixelexia...


« Reply #8 - Posted 2014-01-19 10:52:44 »

A factory is a class or group of functions that creates a "new" instance of an object in java. It is useful for tile maps because each tile is different and needs a different object. If you didn't have a factory you run the risk of overwriting tile data in more than one tile.

In short, factories just make sure that each tile can store its own data.

Offline Jono
« Reply #9 - Posted 2014-01-19 13:57:12 »

Actually, I did some research and didn't find much on the subject. Would you mind giving a very brief explanation of them?
Wikipedia does a good job of explaining it, and even includes some examples in Java:
http://en.wikipedia.org/wiki/Factory_method_pattern
http://en.wikipedia.org/wiki/Abstract_factory_pattern
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Slyth2727
« Reply #10 - Posted 2014-01-19 16:50:30 »

Okay, that makes sense.
So this bit of code here:

1  
2  
3  
4  
interface BlockFactory<T extends BlockSuper>
{
  public T create(Vector3f pos);
}


Is obviously just an interface I would have to implement in my Level class, correct?

And then this bit:

1  
2  
3  
4  
5  
public static final BlockFactory<WallBlock> wallBlockFactory = new BlockFactory<> { 
  public WallBlock create(Vector3f pos){
    return new WallBlock(main, pos);
  }
}


Is the piece that creates the new object. The only thing I don't get about this is that you wrote it as creating WallBlocks instead of the superclass, BlockSuper. Does this mean I have to create one of these methods (or are these their own weird classes.. Unfamiliar syntax for me) for every single block I make, or did you mean to put the superclass and accidentally wrote WallBlock? If it's not the latter it doesn't seem very dynamic, no?

Then this code:

1  
makeWall(start, end, wallBlockFactory);


Is the bit that actually makes the blocks. This is the bit that leads me to believe that I have to create one of those strange  
1  
public static final BlockFactory<WallBlock> wallBlockFactory = new BlockFactory<> { ... }
 things for each individual block.

Was I before Chuang Tzu who dreamt about being a butterfly, or am I now a butterfly who dreams about being Chuang Tzu?
Offline Danny02
« Reply #11 - Posted 2014-01-19 18:08:34 »

Yes, you would have to create a factory for each block type you have. In my previous code I created an anonymous class and stored it in a "singleton", I did it that way so that you don't need to create a new instance of the factory on each "makeBlock" call.

The benefits of not using reflection for this task is type safety and better performance.
Offline Slyth2727
« Reply #12 - Posted 2014-01-19 21:02:47 »

So this is not very dynamic is it? Let's say we have a game with many, many blocks, like the game Minecraft. Does that game use factories? It seems for a game like that this way would not be very good at all.

Excuse me if I'm being a bit irritating, I am trying to get as in depth as possible in order to fully understand it. Feel free to tell me to back off Smiley

Was I before Chuang Tzu who dreamt about being a butterfly, or am I now a butterfly who dreams about being Chuang Tzu?
Offline Danny02
« Reply #13 - Posted 2014-01-19 22:25:51 »

You perhaps have to rethink your solution. Why not have only one data class for Blocks with a type component:
1  
2  
3  
4  
5  
6  
public class Block
{
  public enum Type { Wood, Concrete, Metal; }
 
  public final Type type;
}
Offline Slyth2727
« Reply #14 - Posted 2014-01-20 02:37:08 »

How would that let one do specific things with a single type? Let's say I want to do something when the player ball rolls onto a block, like fill his hearts back up. Wouldn't I need a specific subclass like, RegenBlock or something that overrides onPlayerCollide(PlayerBall player)?

Was I before Chuang Tzu who dreamt about being a butterfly, or am I now a butterfly who dreams about being Chuang Tzu?
Offline Longor1996
« Reply #15 - Posted 2014-01-20 15:48:08 »

Doing it like Minecraft? Here is how:
'Fake'-Singletons, and flat binary data.

More detailed description:

You have one super class called 'Block'.
This class could look like this:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
abstract class Block
{
  String genericName;

  public Block(String genericName)
  {
    this.genericName = genericName;
  }

  public void onPlayerCollide(Player p, int thisBlockX, int thisBlockY, int thisBlockZ){/**Empty**/}
  public void onPlayerClick(Player p, int thisBlockX, int thisBlockY, int thisBlockZ){/**Empty**/}
}


Then you have classes like this:
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  
class RegenBlock extends Block
{
  RegenBlock()
  {
    super("regenBlock");
  }

  public void onPlayerCollide(Player p, int thisBlockX, int thisBlockY, int thisBlockZ)
  {
    p.health++;
  }
}

+////////////////////////////////////////

class ButtonBlock extends Block
{
  ButtonBlock()
  {
    super("buttonBlock");
  }
 
  public void onPlayerClick(Player p, int thisBlockX, int thisBlockY, int thisBlockZ)
  {
    // Do what a button does.
 }
}


Then you have a special class, which stores the existing block-types (not the blocks themself!):
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
class BlockList
{
  Block[] blockList;

  public BlockList()
  {
     blockList = new Block[256];
     blockList[0] = new BlockAir();
     blockList[1] = new RegenBlock();
     blockList[2] = new ButtonBlock();
  }
}


Then you have a chunk-class, like this.
It only stores integers which are nothing more than indexes into the BlockList's "blocks" array.
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
class Chunk
{
    <any-structure-that-can-store-integers> blocks;
   
    public Chunk()
    {
        // set block
       blocks(blabla-integer-setter x/y/z) = 0; // 0 is 'BlockAir' in the BlockList's 'blocks' array.
       blocks(blabla-integer-setter x/y/z) = 1; // 1 is 'RegenBlock' in the BlockList's 'blocks' array.
   }
}


Now then we have this:
1  
2  
3  
4  
5  
6  
7  
// In the method section which does collision and stuff.
int blockColllidedWithX = ...;
int blockColllidedWithY = ...;
int blockColllidedWithZ = ...;
int blockData = ... This is the integer we get from a Chunk's block data-structure.

BlockList[blockData].onPlayerCollide(player, blockColllidedWithZ, blockColllidedWithY, blockColllidedWithZ);


Note that:
- This is quite a long piece of code, written in a haste, so I probably forgot something.
- Read this post multiple times, until you understand it.
- This can also be optimized a LOT, and can be made much more dynamic.
- If you don't understand something, ask me or anyone that understands this.

Have a nice day!

- Longor1996

Sorry for my bad English! That's because i am from Germany.
Offline Slyth2727
« Reply #16 - Posted 2014-01-20 17:55:12 »

That's a very nice approach actually, it makes it so that I only need to create one instance of each block. There are only a few downers I can see that can come from using this approach! I'll go and code it all in and report back if I have any problems. Thanks a bunch!

Edit:

Okay I decided to go with Factories as I decided that I really don't need a large amount of blocks. Because of my collision system sometimes I was getting null when colliding with something because of some  positioning readjustments I had to do. So I ended up making one instance of a new class, Block_Air, and setting everything that wasn't occupied to that one instance. Obviously there are some drawbacks to that, but hey, it works.

Thanks a lot for the help guys. By the way, I re did some of the rendering stuff, check out how it looks now:


Was I before Chuang Tzu who dreamt about being a butterfly, or am I now a butterfly who dreams about being Chuang Tzu?
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.

BurntPizza (14 views)
2014-09-19 03:14:18

Dwinin (32 views)
2014-09-12 09:08:26

Norakomi (58 views)
2014-09-10 13:57:51

TehJavaDev (79 views)
2014-09-10 06:39:09

Tekkerue (40 views)
2014-09-09 02:24:56

mitcheeb (62 views)
2014-09-08 06:06:29

BurntPizza (45 views)
2014-09-07 01:13:42

Longarmx (31 views)
2014-09-07 01:12:14

Longarmx (36 views)
2014-09-07 01:11:22

Longarmx (36 views)
2014-09-07 01:10:19
List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06

List of Learning Resources
by SilverTiger
2014-07-31 11:54:12

HotSpot Options
by dleskov
2014-07-08 01:59:08
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!