LWJGL Forum

Programming => General Java Game Development => Topic started by: EB5473 on July 05, 2012, 21:21:59

Title: Problems with Rendering Multiple Entities
Post by: EB5473 on July 05, 2012, 21:21:59
Hello All!
I am just doing some base work for a entity engine, and i am having problems rendering more than one Entity at a time.
Main File-

package main;

import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import static org.lwjgl.opengl.GL11.*;
public class TheGameMain {
Game game = new Game("TEST");
InputHandler playinput = new InputHandler(game.player);
RenderHandler gameren = new RenderHandler(game);

public void start() {
try {
Display.setDisplayMode(new DisplayMode(800,600));
Display.create();
}
catch(LWJGLException e) {
e.printStackTrace();
System.exit(0);
}

init();

while(!Display.isCloseRequested()) {
gameren.render(game.player);
gameren.render(game.entity1);
playinput.input();
Display.update();

}
Display.destroy();
}


public void init() {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0,800,0,600,1,-1);
}

public static void main(String[] args) {
TheGameMain thegame =  new TheGameMain();
thegame.start();
}
}




"Game"-

package main;

import java.util.Random;

public class Game {
public String name;
public Entity player;
public Entity entity1;
public Random entitynumber;

public Game(String name) {
this.name = name;
player = new Entity();
entity1 = new Entity();
}


}





RenderClass -

package main;

public class RenderHandler {
Game rengame;
public RenderHandler(Game game) {
rengame = game;
}
public void render(Entity entity) {
entity.render();
}

}


I would love if someone could correct me in any respect, or suggest a better way to do it!

Thanks a bunch-
EB
Title: Re: Problems with Rendering Multiple Entities
Post by: frostyfrog on July 05, 2012, 22:18:23
I'm not sure if my way is the best or not (I learned it for Mojang's CatacombSnatch), so hopefully someone else will come up with a better solution.

You could try adding this to Game.java, hopefully it will all work with your current setup:

public Set<Entity> entities = new HashSet<Entity>();
public void addEntity(Entity ent) {
entities.add(ent); // add the entity to a set of entities
}

/*
You could include your player tick code in with all other entities.
Or, if you declare it in your constructor, you can just call player.tick() separately.
*/
public void tick() {
for(Entity ent : entities) { // for EVERY entity
if(ent instanceof Player) { // or replace for your own player checking
//insert player specific tick code
}
ent.tick();
}
}


Then for your render class:

public void render() {
for(Entity ent : rengame.entities) {
ent.render();
}
}


Hope this helps. =)
Title: Re: Problems with Rendering Multiple Entities
Post by: CodeBunny on July 06, 2012, 00:07:27
FYI this is very, very, very bad:


for(Entity ent : entities) { // for EVERY entity
if(ent instanceof Player) { // or replace for your own player checking
//insert player specific tick code
}
ent.tick();
}


Instead, all entities should have a tick() method, and the player should override it and put the player-specific calls there.
Title: Re: Problems with Rendering Multiple Entities
Post by: frostyfrog on July 06, 2012, 00:51:33
Hmm... I should of thought of that, thanks for pointing out my error CodeBunny. :)
Title: Re: Problems with Rendering Multiple Entities
Post by: EB5473 on July 06, 2012, 01:51:43
Well guys, thanks for all your help! Looks like with the proper work i should be on the right track. Now to just work out how to serialize this along with world data...

EDIT:Aaaaanddd...I've run into a problem >.<
The code is a bit hard to use when it comes to assessing specific entities, without using a "instanceof" statement. Would there be any way to append a string to each as a ID for a call or something similar?
Title: Re: Problems with Rendering Multiple Entities
Post by: frostyfrog on July 06, 2012, 04:34:59
As CodeBunny stated, you should override the 'tick' function of each entity that need specific code. The player, for example, would need to be in Player.java. Like so:

package your.package.here

// Your import statements would go here...

public class Player {
public tick() {
super.tick();
// Custom code for the player on tick
}
public render() {
// Player specific render code, super.tick() if you need it.
// If you only need super.tick(), remove this function
}
}


But, if you want to disregard our advice on this matter, you could use the following (messier) code:

// Somewhere else in your code...
Entity player = new Entity();
player.id = 7;
addEntity(player);
/***********************/
public void addEntity(Entity ent) {
entities.add(ent); // add the entity to a set of entities
}
public void tick() {
for(Entity ent : entities) { // for EVERY entity
if(ent.id == 7) {
//insert player specific tick code
}
ent.tick();
}
}


Please note: All the above code was hand typed and there may be some issues with it, since I haven't tested it thoroughly...
Title: Re: Problems with Rendering Multiple Entities
Post by: EB5473 on July 06, 2012, 12:35:37
Finally got everything working...but the game will still only render one entity...
Here's the code i am using in TheGameMain, sorry if i am being completley stupid about this  :-[

package main;

import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import static org.lwjgl.opengl.GL11.*;
public class TheGameMain {
Game game = new Game("TEST");
RenderHandler gameren = new RenderHandler(game);
EntityPlayer player = new EntityPlayer();
Entity entity = new Entity();

public void start() {
try {
Display.setDisplayMode(new DisplayMode(800,600));
Display.create();
}
catch(LWJGLException e) {
e.printStackTrace();
System.exit(0);
}

init();

while(!Display.isCloseRequested()) {
gameren.render();
game.tick();
Display.update();

}
Display.destroy();
}


public void init() {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0,800,0,600,1,-1);
glMatrixMode(GL_MODELVIEW);

game.addEntity(entity);
game.addEntity(player);

game.tick();
}

public static void main(String[] args) {
TheGameMain thegame =  new TheGameMain();
thegame.start();
}
}



Seems like it wants only to render the last entity declared...
Title: Re: Problems with Rendering Multiple Entities
Post by: Fool Running on July 06, 2012, 13:00:54
I think we need to see the contents of your entity render method. Without seeing that code, my best guess is that you might be clearing the view in the render method. ;)
Title: Re: Problems with Rendering Multiple Entities
Post by: EB5473 on July 06, 2012, 14:00:30
*facepalm* Thank you very much Fool Running, that was the problem >.<
Thanks to all who helped me! Now just to figure out how to serialize that list of entities...
Title: Re: Problems with Rendering Multiple Entities
Post by: frostyfrog on July 06, 2012, 16:07:01
Whoops, how did I miss how that was the problem. Oh well.

A bit off of the OP Topic, but I thought I'd share a bit more info. If I'm understanding you correctly, you want to serialize the list of entities and save them to a file. Then you want to deserialize that data to load it back in. It's not exactly the best way, but I'm currently using JSON-Simple (http://code.google.com/p/json-simple/) to save and load my map files. I hope that helps you a bit, at least for a little while anyways. If anyone knows of a better way, I'm all ears as I would like to know too.
Title: Re: Problems with Rendering Multiple Entities
Post by: EB5473 on July 06, 2012, 18:03:04
Looks like it would work, may take a little bit of understanding and implementation, but no worries. The only two problems i can see currently are adding entities dynamically (less of a problem, may be able to find a workaround eventually) and killing(removing) entities from the "entities" list (eg.health goes down below zero, remove entity from screen)
Title: Re: Problems with Rendering Multiple Entities
Post by: frostyfrog on July 06, 2012, 18:42:34
Oh, for removing entities from the entity list dynamically, you could do this:

//in game.java
public void removeEntity(Entity ent) {
entities.add(ent); // add the entity to a set of entities
}
//in, for example, Player.tick()
public void tick() {
if(health <= 0) {
//Some cleanup code
Game.removeEntity(this);
}
}
//add entity to entity list upon creation (in Entity.java)
public Entity() {
Game.addEntity(this);
//Then when ever ANY entity is created, it is added to the list.
}

I'm not sure if java will clean up the class once you remove it from the entities list, but it should (I think).
Title: Re: Problems with Rendering Multiple Entities
Post by: EB5473 on July 06, 2012, 19:18:37
I like that idea, I'll try that. In the mean time, JSON-Simple has worked for me, and I've got a (extremely basic) entity saving system. All I have to do is figure out a way to overwrite if needed, and otherwise append, but that's way off topic. thanks for your help!
Title: Re: Problems with Rendering Multiple Entities
Post by: frostyfrog on July 06, 2012, 19:47:58
Just some food for thought on what you were planning...

I thought it would overwrite by default. If that is the case, then to append, just take it's current data string and append to it wherever needed. Then write back to the file.
Title: Re: Problems with Rendering Multiple Entities
Post by: EB5473 on July 06, 2012, 22:29:52
Well, the only thing thats currently happening(using some convoluted append scheme, as overwriting only saves one entity) is the file will keep getting progressively larger, it wont clear, but will instead just append an updated copy to the end of the file...
EDIT:Using the remove code, i now(off and on) get this lovley error:

Exception in thread "main" java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextEntry(Unknown Source)
at java.util.HashMap$KeyIterator.next(Unknown Source)
at main.Game.tick(Game.java:54)
at main.TheGameMain.start(TheGameMain.java:36)
at main.TheGameMain.main(TheGameMain.java:72)


Here be the code in Game:

package main;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Random;
import java.util.Set;

import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
import org.lwjgl.Sys;
import org.lwjgl.input.Keyboard;

import static org.lwjgl.input.Keyboard.*;


public class Game {
public String name;
public SaveGame saver = new SaveGame();
public Set<Entity> entities = new HashSet<Entity>();
public Random entitynumber;
public boolean saveReady = true;
public int saveCounter;
public boolean spawnReady = true;
public int spawnCounter;
public int screenX = 800;
public int screenY = 600;



JSONObject ents = new JSONObject();


int fps;
long lastFrame;
long lastFPS;

public void addEntity(Entity ent) {
entities.add(ent);
}
public void removeEntity(Entity ent) {
spawnReady = false;
entities.remove(ent);
if(spawnCounter >= 5000)
spawnReady = true;
}

public void tick() {
for(Entity ent : entities) {
ent.tick();
if(ent.pos.y <= 0) ent.pos.y = 0;
if(ent.pos.y + 50 >= 600) ent.pos.y = 550;
if(ent.pos.x <= 0) ent.pos.x = 0;
if(ent.pos.x + 50 >= 800) ent.pos.x = 750;
}

if(isKeyDown(KEY_F)) {
if(saveReady) {
saveReady=false;
for(Entity ent : entities) {
saver.save(ent, this);
}
saveCounter = 0;
}
}
if(isKeyDown(KEY_G)) {
if(spawnReady) {
spawnReady =false;
addEntity(new EntityMob("Mob",this));
spawnCounter = 0;
}
}
saveCounter++;
spawnCounter++;
if(saveCounter >= 5000) {
saveReady = true;
}
if(spawnCounter >= 5000) {
spawnReady = true;
}
System.out.println(spawnReady);
}



public long getTime() {
   return (Sys.getTime() * 1000) / Sys.getTimerResolution();
}

public Game(String name) {
this.name = name;
}

}
Title: Re: Problems with Rendering Multiple Entities
Post by: Fool Running on July 09, 2012, 13:00:35
It looks like Entity.tick() can remove itself from the entities list? If that's the case, then you would need to keep a separate list of entities that were deleted and delete them after running through the tick() loop. Alternately, if an entity can only ever delete itself, you could do a reverse 'for' loop (instead of a foreach) which would keep the removed item from affecting the tick() loop.
Title: Re: Problems with Rendering Multiple Entities
Post by: EB5473 on July 14, 2012, 22:55:01
Only problem I can see with that is the fact that it would seem EVERYTHING needs to run through the tick() loop to actually run. I'll see what I can engineer, and maybe I'm not understanding it quite right, but let's see.
Title: Re: Problems with Rendering Multiple Entities
Post by: EB5473 on July 19, 2012, 18:10:53
I'm not figuring it out. Anyone else have an idea on how to fix this?
Title: Re: Problems with Rendering Multiple Entities
Post by: CodeBunny on July 19, 2012, 18:18:06
This question seems to have morphed. Can you restate the issue you're working against now?
Title: Re: Problems with Rendering Multiple Entities
Post by: EB5473 on July 19, 2012, 23:24:25
Sorry, your right...
I'm working against a ConcurrentModificationError
Title: Re: Problems with Rendering Multiple Entities
Post by: basil on September 03, 2012, 23:02:44
you have probably a nested remove() in a iteration over the list itself.

you can use a list or set that works with concurrent access or you have to que all read and write properly in you game loop.