Jump to content

  • Log In with Google      Sign In   
  • Create Account

We're offering banner ads on our site from just $5!

1. Details HERE. 2. GDNet+ Subscriptions HERE. 3. Ad upload HERE.


mickd

Member Since 31 Oct 2009
Offline Last Active Mar 20 2012 11:39 PM

Topics I've Started

recommended ways of storing game entities and state game structure

13 March 2012 - 07:24 AM

I'm working on a very simple 2d tile-based game for educational purposes and have a question about how the game entities should be stored and drawn, and a question about the design of a state based game.

For the first question:

The simplest way seems to be just to store them in a List structure (for example, a list of Monsters) but my concerns start to arise when you potentially have a list of thousands of monsters on the map.

When displaying the monsters, you would only need to draw the ones that are visible on the screen (within a set amount of tiles from the player). Would there be a better way than to iterate over the list every frame to calculate which monsters are close enough to the player to be drawn, then draw them?

For the second question:

I currently have a ResourceManager class which has a static reference to a KeyHandler and a MouseHandler class, amongst other things. This is currently allowing me to easily call the key and mouse handlers from any of my states, since I can just go ResourceManager.getKeyHandler(). Is this bad practice? If so, any suggestions? I've actually got a very similar thing with an EntityManager which has static calls to retrieve things like the current Player class and list of Npcs/Monsters, etc.

Thanks for any input, it will be greatly appreciated.

Adding values to FloatBuffers

09 April 2011 - 05:05 AM

Hi guys, I've stumbled across a bug in my code. A few of my friends and i have all had a look through it, and still cant figure it out. I also posted this on the opengl official forums a while ago, but since FloatBuffer is a java implementation, i thought it might be more appropriate to post it here!

Any help greatly appreciated!

The program:
I'm creating a flame in a simple particle system. It has the ability to do the bezier calculations on the cpu or through the shader (toggle-able). Adding particles while its rendering without using the shader works perfectly.

The problem:
When i turn on the shader, adding particles to the FloatBuffers behave unexpectedly.

Say i have my current floatbuffer, which can hold 3000 floats (before it buffer overflows), and i have exactly 3000 floats in it. While not using the shader, if i increase the number of floats to 4500, my code creates a new floatbuffer that can hold double the previous one (6k floats), copies the old 3000 floats into it, and adds the new 1500 floats ontop of it.

The result is i have a float buffer that can hold 6000 floats, and has 4500 in it currently.

When i do the same thing when the shader is turned in, instead of adding the 1500 extra floats ontop of the 3000, it seems like its wiping the buffer clean, and adding the 1500 new floats.

The result is i have a float buffer that can hold 3000 still (since it never tried to add the 3001st float, the function never creates a bigger buffer), but with only 1500 floats (the new floats i think) only.

I hope that makes some sense. The weird thing is, its the exact same createParticle() code that is being called when the cpu calculated flame or the shader calculated flame is running.

All attributes are bound and passed successfully into the vertex shader this time!

Here's hopefully all the relevant code...

The drawing code: drawParticles is called in display()
	double lastRendered = System.currentTimeMillis();
	
	protected void drawParticles(GL gl) {
    	
    	gl.glColor4f(0.7f, 0.2f, 0.1f, 0.8f);
    	gl.glPointSize(20);
    	
    	if(useShader) {
            
            GPUrenderer(gl);
    	}
    	else {
            
            CPUrenderer(gl);
    	}
    	
    	if((System.currentTimeMillis() - lastRendered) >= 30) {
            
            time += 0.03f;
            lastRendered = System.currentTimeMillis();
    	}
    	
    	if(time > 1) time = 0;
	}
	
	private void CPUrenderer(GL gl) {
    	
    	gl.glUseProgram(0);
    	
    	gl.glBegin(GL.GL_POINTS);
    	
    	FlameParticle particle;
    	Vector3D particleLocation;
    	
    	for(int i = 0; i < particleList.size(); i++) {
            
            particle = (FlameParticle)particleList.get(i);
            
            particleLocation = particle.currPosition(time);
            
            gl.glVertex3f(particleLocation.x, particleLocation.y, particleLocation.z);
    	}
    	
    	gl.glEnd();
	}
	
	private void GPUrenderer(GL gl) {
    	
    	gl.glUseProgram(shader.getProgram());
    	
    	gl.glUniform1f(gl.glGetUniformLocation(shader.getProgram(), "time"), time);
    	
//        System.out.println(cp1.capacity());
    	
    	
    	cp0.rewind();
    	gl.glVertexPointer(3, GL.GL_FLOAT, 0, cp0); // bezier cp0
    	cp1.rewind();
    	gl.glVertexAttribPointer(BEZIER_CP1, 3, GL.GL_FLOAT, false, 0, cp1);
    	cp2.rewind();
    	gl.glVertexAttribPointer(BEZIER_CP2, 3, GL.GL_FLOAT, false, 0, cp2);
    	cp3.rewind();
    	gl.glVertexAttribPointer(BEZIER_CP3, 3, GL.GL_FLOAT, false, 0, cp3);
    	startTime.rewind();
    	gl.glVertexAttribPointer(START_TIME, 1, GL.GL_FLOAT, false, 0, startTime);
    	
    	gl.glEnableClientState(GL.GL_VERTEX_ARRAY); // bezier cp0
//        gl.glEnableVertexAttribArray(BEZIER_CP0);
    	gl.glEnableVertexAttribArray(BEZIER_CP1);
    	gl.glEnableVertexAttribArray(BEZIER_CP2);
    	gl.glEnableVertexAttribArray(BEZIER_CP3);
    	gl.glEnableVertexAttribArray(START_TIME);

    	gl.glDrawArrays(GL.GL_POINTS, 0, particleList.size());
    	
    	gl.glDisableClientState(GL.GL_VERTEX_ARRAY); // bezier cp0
//        gl.glDisableVertexAttribArray(BEZIER_CP0);
    	gl.glDisableVertexAttribArray(BEZIER_CP1);
    	gl.glDisableVertexAttribArray(BEZIER_CP2);
    	gl.glDisableVertexAttribArray(BEZIER_CP3);
    	gl.glDisableVertexAttribArray(START_TIME);
	}

setting up the floatbuffers initially, called in init()
	protected FloatBuffer cp0, cp1, cp2, cp3, startTime;
	
	protected void setupBuffers() {
		
		cp0 = BufferUtil.newFloatBuffer(3 * 1000);
		cp1 = BufferUtil.newFloatBuffer(3 * 1000);
		cp2 = BufferUtil.newFloatBuffer(3 * 1000);
		cp3 = BufferUtil.newFloatBuffer(3 * 1000);
		startTime = BufferUtil.newFloatBuffer(1000);
	}

addParticles(amount to add) called when i press + on the keyboard
	private void addParticles(int toAdd) {
		
		int count = 0;
		
		while(count < toAdd) {
			
			createParticle();
			
			count++;
		}
	}

	protected void createParticle() {
		
		FlameParticle particle = new FlameParticle();
		
		particleList.add(particle);
		
		FloatBuffer temp;
		
		if(cp0.remaining() < 3) {
			System.out.println("here");
//			cp0.rewind();
			temp = BufferUtil.newFloatBuffer(cp0.capacity());
			temp.put(cp0);
			temp.rewind();
			cp0.rewind();
			cp0 = BufferUtil.newFloatBuffer(cp0.capacity() * 2);
			cp0.put(temp);
//			cp0.position(temp.position());
		}
		
		if(cp1.remaining() < 3) {
			
//			cp1.rewind();
			temp = BufferUtil.newFloatBuffer(cp1.capacity());
			temp.put(cp1);
			temp.rewind();
			cp1.rewind();
			cp1 = BufferUtil.newFloatBuffer(cp1.capacity() * 2);
			cp1.put(temp);
//			cp1.position(temp.position());
		}
		
		if(cp2.remaining() < 3) {
			
//			cp2.rewind();
			temp = BufferUtil.newFloatBuffer(cp2.capacity());
			temp.put(cp2);
			temp.rewind();
			cp2.rewind();
			cp2 = BufferUtil.newFloatBuffer(cp2.capacity() * 2);
			cp2.put(temp);
//			cp2.position(temp.position());
		}
		
		if(cp3.remaining() < 3) {
			
//			cp3.rewind();
			temp = BufferUtil.newFloatBuffer(cp3.capacity());
			temp.put(cp3);
			temp.rewind();
			cp3.rewind();
			cp3 = BufferUtil.newFloatBuffer(cp3.capacity() * 2);
			cp3.put(temp);
//			cp3.position(temp.position());
		}
		
		if(startTime.remaining() < 1) {
			
//			startTime.rewind();
			temp = BufferUtil.newFloatBuffer(startTime.capacity());
			temp.put(startTime);
			temp.rewind();
			startTime.rewind();
			startTime = BufferUtil.newFloatBuffer(startTime.capacity() * 2);
			startTime.put(temp);
//			startTime.position(temp.position());
		}
		
//		System.out.println(cp0.position());
		
//		cp0.position((particleList.size()-1)*3);
//		cp1.position((particleList.size()-1)*3);
//		cp2.position((particleList.size()-1)*3);
//		cp3.position((particleList.size()-1)*3);
//		startTime.position(particleList.size()-1);
		
		cp0.put(particle.cp0.x);
		cp0.put(particle.cp0.y);
		cp0.put(particle.cp0.z);
		
		cp1.put(particle.cp1.x);
		cp1.put(particle.cp1.y);
		cp1.put(particle.cp1.z);
		
		cp2.put(particle.cp2.x);
		cp2.put(particle.cp2.y);
		cp2.put(particle.cp2.z);
		
		cp3.put(particle.cp3.x);
		cp3.put(particle.cp3.y);
		cp3.put(particle.cp3.z);
		
		startTime.put(particle.startTime);
		
		System.out.println(cp0.position());
		System.out.println("remaining " + cp0.remaining());
		System.out.println("capacity " + cp0.capacity());
		
	}


I hope that's everything relevant. To recap: when i toggle "useShader" to true, adding to FloatBuffers seems to "clear" the buffer before adding particles. When "useShader" is false, FloatBuffer's work as intended.

Once again, any help would be greatly appreciated!!

[java] Simple square doesn't always display using jogl2

12 June 2010 - 07:31 PM

Hey guys, I'm using jogl2.0 b10 testing an extremely simple program that's supposed to well.. just display a square in the center.

I'm not sure why, but only certain screen size ratios display the square (only if the screen height is greater than the width by a margin).

If anyone could have a look for me, that would be great!


import javax.media.opengl.GL2;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.awt.GLCanvas;
import javax.media.opengl.glu.GLU;
import javax.swing.JFrame;

import com.sun.opengl.util.FPSAnimator;



public class Loader extends JFrame implements GLEventListener {

private GLCapabilities glCaps = null;
private GLCanvas glCanvas = null;

private FPSAnimator animator = null;

private static final long serialVersionUID = 211350059027795801L;

/**
* @param args
*/

public static void main(String[] args) {

new Loader().run();
}

public Loader() {

super("Test");

glCaps = new GLCapabilities(null);
glCaps.setDoubleBuffered(true);
glCanvas = new GLCanvas(glCaps);

glCanvas.addGLEventListener(this);

animator = new FPSAnimator(glCanvas, 25);

getContentPane().add(glCanvas);


}

public void run() {

setSize(800, 600);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);

animator.start();
}

@Override
public void display(GLAutoDrawable drawable) {

GL2 gl = drawable.getGL().getGL2();

gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);

gl.glLoadIdentity();

//gl.glTranslatef(-1.5f, 0.0f, -6.0f);

gl.glBegin(GL2.GL_POLYGON);
gl.glVertex3f(-0.5f, -0.5f, 0.0f);
gl.glVertex3f(-0.5f, 0.5f, 0.0f);
gl.glVertex3f(0.5f, 0.5f, 0.0f);
gl.glVertex3f(0.5f, -0.5f, 0.0f);
gl.glEnd();

gl.glFlush();

drawable.swapBuffers();
}

@Override
public void dispose(GLAutoDrawable arg0) {
// TODO Auto-generated method stub

}

@Override
public void init(GLAutoDrawable glad) {

GL2 gl = glad.getGL().getGL2();

// set smooth shading
gl.glShadeModel(GL2.GL_SMOOTH);

// set clear colour to black
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

// set the depth buffer on
gl.glClearDepth(1.0f);
gl.glEnable(GL2.GL_DEPTH_TEST);
gl.glDepthFunc(GL2.GL_LEQUAL);

// gl.glDepthRange(0.0f, 1.0f);

// set perspective correction
gl.glHint(GL2.GL_PERSPECTIVE_CORRECTION_HINT, GL2.GL_NICEST);
}

@Override
public void reshape(GLAutoDrawable glad, int x, int y, int width, int height) {

GL2 gl = glad.getGL().getGL2();
GLU glu = new GLU();

// prevent division by 0 on height
if(height == 0) height = 1;

gl.glViewport(0, 0, width, height);
gl.glMatrixMode(GL2.GL_PROJECTION);
gl.glLoadIdentity();
glu.gluPerspective(45.0f, width/height, 0.1f, 100.0f);

gl.glMatrixMode(GL2.GL_MODELVIEW);
gl.glLoadIdentity();
}

}



PARTNERS