Java-Gaming.org    
Featured games (91)
games approved by the League of Dukes
Games in Showcase (581)
games submitted by our members
Games in WIP (500)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
   Home   Help   Search   Login   Register   
  Show Posts
Pages: [1]
1  Game Development / Newbie & Debugging Questions / Re: Smooth transition between angles on: 2014-03-10 04:03:14
Rest well sir.  What I have is working flawlessly for my little space shooter project.  Like I said, I haven't tried every angle yet, but it seems to work for what I need.  Marking this one solved.
2  Game Development / Newbie & Debugging Questions / Re: Smooth transition between angles on: 2014-03-10 03:42:23
Yeah the one thing I hate about libgdx.  Getting used to that fact that Y is up! 
3  Game Development / Newbie & Debugging Questions / Re: Smooth transition between angles on: 2014-03-10 03:28:37
After some playing around, I might have something that works.  At least for transitioning from 0 to 270 and then from 180 back to 270.  Haven't tried other angles yet but here it is for those that are interested.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
public void doBehavior(GameObject g)
   {
      int currentDirection = g.getDirection();
       
      if(currentDirection == 0) currentDirection = 360;
     
      if(currentDirection < direction)
      {
         g.setDirection(currentDirection + 1);
      }
     
      else if(currentDirection > direction)
      {
         g.setDirection(currentDirection - 1);
      }
     
   }
4  Game Development / Newbie & Debugging Questions / Re: Smooth transition between angles on: 2014-03-10 03:23:49
Thanks for trying.  I guess I'll keep playing around and see what I can come up with.
5  Game Development / Newbie & Debugging Questions / Re: Smooth transition between angles on: 2014-03-10 03:10:09
Hmmm this makes him turn and go up.  I tried reversing the plus and minus but he just does a loop.  God I wish I'd studied trig in school...
6  Game Development / Newbie & Debugging Questions / Re: Smooth transition between angles on: 2014-03-10 03:04:23
In your last post you said: if diff1 < diff2 then turn left, else turn right (it could be opposite though ;P).  But what do you mean by turn left?  Do I add to the currentDirection?
7  Game Development / Newbie & Debugging Questions / Re: Smooth transition between angles on: 2014-03-10 03:00:23
I get what you're saying, but my movement is based on sin and cos, so how would this look in code?  The only way I can see is to either add or subtract from the currentDirection which works if he's moving left but not for moving right.  ?? 
8  Game Development / Newbie & Debugging Questions / Re: Smooth transition between angles on: 2014-03-10 02:54:51
Ok here is what I have so far:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
   public void doBehavior(GameObject g)
   {
      int currentDirection = g.getDirection();
      int diff1 = currentDirection - direction;
      int diff2 = direction - currentDirection;
     
      if(diff1 < 0) diff1 += 360;
      else if(diff1 > 360) diff1 -= 360;
   
      if(diff2 < 0) diff2 += 360;
      else if(diff2 > 360) diff2-= 360;
     
      // Now what do I do with these numbers?
     
   }
9  Game Development / Newbie & Debugging Questions / [Solved] Smooth transition between angles on: 2014-03-10 02:37:36
Hey guys,

I trying to create some simple AI for my enemy class.  I have an enemy moving 0 degrees initially, and I want to make him move smoothly to angle 270 (straight down in my coordinate system).  How can this be done?  

With my current code, he ends up "taking the long way around" so to speak but it works fine for transitioning from 180 to 270 (left to down).  I'm looking for something that will transition smoothly no matter what the chosen direction is and preferably so he would take the shortest route to get there.

This seems like it should be simple, but it's driving me nuts!  I am posting my code below which doesn't quite work.  In the below example, the variable direction is fixed at 270.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
public void doBehavior(GameObject g)
   {
      int currentDirection = g.getDirection();
     
      // Smooth transition from current direction to new
     
     
      if(currentDirection < direction)
      {
         g.setDirection(currentDirection + 1);
      }
     
      else if(currentDirection > direction)
      {
         g.setDirection(currentDirection - 1);
      }
     
   }
10  Game Development / Newbie & Debugging Questions / Re: null objects in ArrayList on: 2014-02-23 05:14:44
@BurntPizza:  I have read that post and found it interesting.  My issue seemed to be due to a bad implementation of the Thread.sleep on windows platform (or so I've read) which caused the sleep time to be innacurate so I just wanted to see how the game would run from a steady timer "tick" if you will.  Also, I'm not using swing with the exception of JFrame I suppose.
11  Game Development / Newbie & Debugging Questions / Re: null objects in ArrayList on: 2014-02-23 05:09:56
@Drenius should I remove the Runnable interface altogether?  I'm actually more experienced with LWJGL than I am with Java 2D, but every tutorial/example code I've ever seen implements Runnable.
12  Game Development / Newbie & Debugging Questions / Re: null objects in ArrayList on: 2014-02-23 05:07:42
@opiop64: Well I'm assuming there is three based on the output of the stack trace.  The application itself, the GamePanel class, and the GameLoop class which as I mentioned is just an experiment and the bug occurred before I implemented that.
13  Game Development / Newbie & Debugging Questions / Re: null objects in ArrayList on: 2014-02-23 05:03:08
Thanks I appreciate your time.  The GamePanel is my engine which runs on it's own thread.  The GameLoop class is just a class which extends java.util.Timer and java.util.TimerTask to tell me when to update and redraw.  It doesn't do any heavy lifting and was just an experiment because I wasn't happy with the commented game loop code you see above.  I should mention that the bug occurred even without a third thread (i.e. the GameLoop class).

I have yet to find an "ideal" game loop that works for me without occasional lag, but that's another story.   Wink
14  Game Development / Newbie & Debugging Questions / Re: null objects in ArrayList on: 2014-02-23 04:55:00
It's pretty rare and random which is what makes it so annoying.  At one point I thought that it seemed to occur when there were many objects on the screen at once, but there's no definite pattern that I can find.  

EDIT: At no point in the game do I actually set any object to null, I only set it's alive boolean to false.  In my mind, this means that only the ObjectManager class will remove objects from the list which I guess is where garbage collection comes in.
15  Game Development / Newbie & Debugging Questions / Re: null objects in ArrayList on: 2014-02-23 04:41:54
Could this be some sort of multi threading issue?  I am posting my GamePanel class below:
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  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
97  
98  
99  
100  
101  
102  
103  
104  
105  
106  
107  
108  
109  
110  
111  
112  
113  
114  
115  
116  
117  
118  
119  
120  
121  
122  
123  
124  
125  
126  
127  
128  
129  
130  
131  
132  
133  
134  
135  
136  
137  
138  
139  
140  
141  
142  
143  
144  
145  
146  
147  
148  
149  
150  
151  
152  
153  
154  
155  
156  
157  
158  
159  
160  
161  
162  
163  
164  
165  
166  
167  
168  
169  
170  
171  
172  
173  
174  
175  
176  
177  
178  
179  
180  
181  
182  
183  
184  
185  
186  
187  
188  
189  
190  
191  
192  
193  
194  
195  
196  
197  
198  
199  
200  
201  
202  
203  
204  
205  
206  
207  
208  
209  
210  
211  
212  
213  
214  
215  
216  
217  
218  
219  
220  
221  
222  
package shooter.engine;

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferStrategy;

import shooter.game.PlayScreen;

@SuppressWarnings("serial")
public class GamePanel extends Canvas implements Runnable, KeyListener, MouseMotionListener, MouseListener
{
   public static final String GAME_NAME = "SHOOTER v1.0";
   public static final int WIDTH = 1024;
   public static final int HEIGHT = 768;
   
   private Thread thread;
   private boolean running;
   
   private int FPS = 60;
   private int targetTime = 1000 / FPS;
   
   private Graphics2D g;
   private BufferStrategy bs;
   
   private ScreenManager scm;
   private GameLoop gameLoop;
   
   public GamePanel()
   {
      super();
      setPreferredSize(new Dimension(WIDTH, HEIGHT));
      setFocusable(true);
      requestFocus();
      setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
   }
   
   private void init()
   {
      running = true;
     
      createBufferStrategy(2);
      bs = getBufferStrategy();
      setIgnoreRepaint(true);
     
      Graphics2D gTemp = (Graphics2D) bs.getDrawGraphics();
     
      gTemp.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
      gTemp.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
     
      scm = new ScreenManager();
      scm.changeScreen(new PlayScreen(scm));
     
      gameLoop = new GameLoop(targetTime);
     
      // Load game sounds
     
      SoundManager.add("laser");
      SoundManager.add("explosion");
      SoundManager.add("powerup");
      SoundManager.add("hit");
      SoundManager.add("powerup");
      SoundManager.add("boost");
     
   }
   
   @Override
   public void addNotify()
   {
      super.addNotify();
      addKeyListener(this);
      addMouseListener(this);
      addMouseMotionListener(this);
      init();
     
      // THREAD START
     if(thread == null)
      {
         thread = new Thread(this);
         thread.setDaemon(true);
         thread.start();
      }
   }

   @Override
   public void run()
   {
      /*long startTime;
      long urdTime;
      long waitTime;
         
      while(running)
      {
         startTime = System.nanoTime();
         
         update();
         draw();
         Toolkit.getDefaultToolkit().sync();
         
         urdTime = (System.nanoTime() - startTime) / 1000000;
         waitTime = (long) (targetTime - urdTime);
         
         if(waitTime < 0) waitTime = 5;
         try
         {
            Thread.sleep(waitTime);
         }
         
         catch(Exception e)
         {
            e.printStackTrace();
         }
      }*/

     
      while(running)
      {
         if(gameLoop.redraw())
         {
            update();
            draw();
            gameLoop.setRedraw(false);
         }
           
      }  
   }
   
   private void update()
   {
      scm.update();
   }
   
   private void draw()
   {
      g = (Graphics2D) bs.getDrawGraphics();
      g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
      g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
     
      // Clear the screen
     
      g.setColor(Color.BLACK);
      g.fillRect(0, 0, WIDTH, HEIGHT);
     
      // Draw game content here
     
      scm.draw(g);
     
      // Render to the screen
     
      g.dispose();
      bs.show();
   }
   
   @Override
   public void keyPressed(KeyEvent key)
   {
      int keyCode = key.getKeyCode();
      scm.keyPressed(keyCode);
   }

   @Override
   public void keyReleased(KeyEvent key)
   {
      int keyCode = key.getKeyCode();
      scm.keyReleased(keyCode);
   }

   @Override
   public void keyTyped(KeyEvent key)
   {
     
   }

   @Override
   public void mouseDragged(MouseEvent e)
   {
      scm.mouseMoved(e);
   }

   @Override
   public void mouseMoved(MouseEvent e)
   {
      scm.mouseMoved(e);
   }

   @Override
   public void mouseClicked(MouseEvent e)
   {
     
   }

   @Override
   public void mouseEntered(MouseEvent e)
   {
     
   }

   @Override
   public void mouseExited(MouseEvent e)
   {
     
   }

   @Override
   public void mousePressed(MouseEvent e)
   {
      scm.mousePressed(e);
   }

   @Override
   public void mouseReleased(MouseEvent e)
   {
     
   }
}
16  Game Development / Newbie & Debugging Questions / Re: null objects in ArrayList on: 2014-02-23 04:29:50
Any other ideas?  This is annoying bug that's slowing my progress on the game and I'm not even sure how to start debugging it.  Sometimes I can play through the game 10 times without incident and then suddenly the crash occurs. 
17  Game Development / Newbie & Debugging Questions / Re: null objects in ArrayList on: 2014-02-23 04:04:27
For my Enemy class:
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  
@Override
   public void destroy()
   {
      SoundManager.play("explosion");
      ObjectManager.add(new Explosion(x,y));
     
      // Type 4 and 5 enemies break into smaller types
     
      if(type == MAMA_YELLOW)
      {
         ObjectManager.add(new Enemy(x,y,BABY_YELLOW));
         ObjectManager.add(new Enemy(x,y,BABY_YELLOW));
         ObjectManager.add(new Enemy(x,y,BABY_YELLOW));
      }
     
      if(type == MAMA_MAGENTA)
      {
         for(int i=0; i<10; i++)
         {
            ObjectManager.add(new Enemy(x,y,BABY_MAGENTA));
         }
      }
     
      // Chance for powerup
     
      int chance = (int) (Math.random() * 100);
     
      if(chance < 5) ObjectManager.add(new PowerUp(x,y,PowerUp.EXTRA_LIFE));
      else if(chance < 20) ObjectManager.add(new PowerUp(x,y,PowerUp.SLOW_DOWN));
      else if(chance < 60) ObjectManager.add(new PowerUp(x,y,PowerUp.POWER));
     
   }


The destroy method was intended to allow one object to "change" into another.  Most of the logic for setting an object as "dead" occurs in the collision events.

EDIT:  @BurntPizza:  Thanks for the info on i--.  I've often wondered why people do this.  This doesn't seem to be the cause of the problem though as the crash occurs with or without it.
18  Game Development / Newbie & Debugging Questions / Re: null objects in ArrayList on: 2014-02-23 03:55:28
I'm not.  I'm only adding with the new operator.   Huh
19  Game Development / Newbie & Debugging Questions / null objects in ArrayList on: 2014-02-23 03:31:56
Hey guys,

I am getting an occasional null pointer exception in my games ObjectManager class.  I can't seem to find a pattern as to why this is happening and could use some help.  Every object in my game is added and removed by this ObjectManager class by checking the objects alive property.  This property is set in collision methods when two objects collide so that the ObjectManager knows when to remove them.

Below is the ObjectManager update method:
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  
public void update()
   {
      GameObject a, b;
     
      // Update the objects and cull the dead
     
      for(int i=0; i<objects.size(); i++)
      {
     
         objects.get(i).update();
         
         if(objects.get(i).isAlive() == false)
         {
            objects.get(i).destroy();
            objects.remove(i);
     
         }
         
      }
     
      // Check for collision
     
      for(int i=0; i<objects.size(); i++)
      {
         for(int j=i; j<objects.size(); ++j)
         {
            a = objects.get(i);
            b = objects.get(j);
           
            if(a == b) continue;
           
            // Finally do the test and alert both objects
           
            if(collision(a,b))
            {
               a.collision(b);
               b.collision(a);
            }
           
           
         }
         
      }
     
     
   }


Here is my relevant stack trace:
1  
2  
3  
4  
5  
6  
7  
8  
Exception in thread "Thread-3" java.lang.NullPointerException
   at shooter.engine.ObjectManager.collision(ObjectManager.java:110)
   at shooter.engine.ObjectManager.update(ObjectManager.java:83)
   at shooter.game.PlayScreen.update(PlayScreen.java:33)
   at shooter.engine.ScreenManager.update(ScreenManager.java:15)
   at shooter.engine.GamePanel.update(GamePanel.java:137)
   at shooter.engine.GamePanel.run(GamePanel.java:127)
   at java.lang.Thread.run(Unknown Source)


Here is the collision method from the stack trace:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
   private boolean collision(GameObject a, GameObject b)
   {
         
      double dx = a.getX() - b.getX();
      double dy = a.getY() - b.getY();
     
      double dist = Math.sqrt(dx * dx + dy * dy);
      if(dist < a.getR() + b.getR()) return true;
     
      return false;
   }


The line that it's pointing to is in the collision method.  I don't see how it could be null because "dead" objects are removed before checking for collision.  The crash doesn't always occur in the collision method, sometimes it occurs in the update method posted above.  Any ideas?  I would be happy to post more code if needed.
20  Game Development / Newbie & Debugging Questions / Re: Struggling with blending on: 2014-01-09 03:47:48
Ok this one was a noobish mistake.  I forgot to disable texturing when drawing the overlay.

Relevent code that now works as expected:

The Quad class draw method:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
   public void draw(float x, float y)
   {
      glDisable(GL_TEXTURE_2D);
      glEnableClientState(GL_VERTEX_ARRAY);
      glEnableClientState(GL_COLOR_ARRAY);
     
      glVertexPointer(2, 0, vertexData);
      glColorPointer(4, 0, colorData);
     
      glPushMatrix();
      glTranslatef(x,y,0);
      glDrawArrays(GL_QUADS, 0, 4);
      glPopMatrix();
     
      glDisableClientState(GL_VERTEX_ARRAY);
      glDisableClientState(GL_COLOR_ARRAY);
      glEnable(GL_TEXTURE_2D);
   }


Gefs code from my World class:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
   @Override
   public void draw()
   {
      float light = sun.getLightLevel();
     
      //float light = 0.3f;  // Just to make it night for debugging
     
      nightSky.draw(camera.getX() + Game.getWidth() / 2, camera.getY() + Game.getHeight() / 2);
      daySky.setTransparency(light);
      daySky.draw(camera.getX() + Game.getWidth() / 2, camera.getY() + Game.getHeight() / 2);
      tileMap.draw();
      player.draw();
     
      // Draw the overlay
     
      quad.setColor(0, 0, 0, 0.8f-light);
      quad.draw(camera.getX() + Game.getWidth() / 2, camera.getY() + Game.getHeight() / 2);

   }
21  Game Development / Newbie & Debugging Questions / Re: Struggling with blending on: 2014-01-09 02:12:21
Gef it works sort of.  For some reason I can only see the effect when I hover the mouse over a block.  In my player code I draw a selector which is just a sprite with a transparent center and black frame to show the selected block.

This one has no effect:
https://www.dropbox.com/s/k57atnvphs8kkll/1.png

This one works as expected as my mouse is over a selectable block:

https://www.dropbox.com/s/d6hlqnbgn3cglrk/2.png

I'm so close if I could just figure this part out!  If you look closely at the second image, you will notice I have a leaf block selected.  When I select any block which triggers the drawing of the selector box, the darkening effect becomes visible.

EDIT:  When I draw the player after drawing the overlay, the problem disappears but the player does not darken with the rest of the scene.  Weird...  I welcome any thoughts.

My updated drawing code:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
   //float light = sun.getLightLevel();
     
      float light = 0.3f;  // Just to make it night for debugging
     
      nightSky.draw(camera.getX() + Game.getWidth() / 2, camera.getY() + Game.getHeight() / 2);
      daySky.setTransparency(light);
      daySky.draw(camera.getX() + Game.getWidth() / 2, camera.getY() + Game.getHeight() / 2);
      tileMap.draw();
      player.draw();
     
      // Draw the overlay
     
      quad.setColor(0, 0, 0, 1.0f-light);
      quad.draw(camera.getX() + Game.getWidth() / 2, camera.getY() + Game.getHeight() / 2);
      /*glBegin(GL_QUADS);
      glColor4f(0.0f, 0.0f, 0.0f, 1.0f-light);
      glVertex2f(0,0);
      glVertex2f(Game.getWidth(),0);
      glVertex2f(Game.getWidth(),Game.getHeight());
      glVertex2f(0,Game.getHeight());
      glEnd();*/
22  Game Development / Newbie & Debugging Questions / Re: Struggling with blending on: 2014-01-09 00:33:46
Danny it's an interesting tool but I cannot duplicate what I need with it either.  Any other suggestions?
23  Game Development / Newbie & Debugging Questions / [Solved] Struggling with blending on: 2014-01-08 23:48:04
Hi Guys,

I am making a 2D minecraft sort of game and all has gone well so far, but I'm stumped on something and am unable to find an answer online.  

I first draw night sky image and then a day sky image on top of the night image.  I then have a Sun class that returns a light level as a float which I then use to control the opacity of the night image so that it fades to night time which works fine.

The problem is that the rest of my world, ie the trees, grass, player etc still looks the same even at night.  Blending is enabled in my Game class and below is what I tried but I just get a black screen.  I have tried multiple blending modes to try to achieve a sort of multiply effect but nothing is working.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
// Draw the overlay after everything else is drawn
     
      glBlendFunc(GL_DST_COLOR, GL_ZERO);
      glBegin(GL_QUADS);
      glColor3f(1.0f * light, 1.0f * light, 1.0f * light);
      glVertex2f(0,0);
      glVertex2f(Game.getWidth(),0);
      glVertex2f(Game.getWidth(),Game.getHeight());
      glVertex2f(0,Game.getHeight());
      glEnd();
      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);


I should mention that my default blend function is glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) and I would be grateful for some direction.  I have tried reading about blend modes and I understand the concept but I can't seem to get what I am looking for.  I simply want to slowly darken what is already on the screen.
24  Game Development / Newbie & Debugging Questions / Re: Texture atlas bleeding w/mipmap on: 2013-08-22 17:18:40
EDIT:  I tried the texture packer you suggested with duplicate and edge padding to regenerate the sheet and it made no difference.  Still seeing the bleeding.

Quote
When you have too tightly packed an atlas, you will end up with bleeding where linear filtering samples neighbouring pixels. See here:
http://www.java-gaming.org/topics/bleeding/26823/msg/237162/view.html#msg237162

This post seems to suggest not to use GL_LINEAR but if I don't my scaled textures look really bad hence my frustration.  Also, I am seeing the bleeding even though my tiles are not scaled.

My original sprite sheet design divided the sheet into individual textures but I was quickly informed that this a no-no!  I must tell you though, my original design works flawlessly when it comes to rendering with no bleeding, strange artifacts or noticeable change in performace.

Dave I should have mentioned that I am scaling down from 256x256 and really didn't want to use mipmapping but it made everything nice and smooth.  What about setting filtering to GL_NEAREST just for my static tiles?  Is this possible?  Hmmm.

Quote
If you are targeting newer desktops, you could instead use GL_TEXTURE_2D_ARRAY.

Would this require a major change in my code?  I realize that most of my code is considered legacy opengl but I am still learning.  At least I have vertex arrays working nicely though.

But I digress, I really want to perfect a technique using a texture atlas so I'm not giving up yet!   Pointing
25  Game Development / Newbie & Debugging Questions / Texture atlas bleeding w/mipmap on: 2013-08-22 16:42:38
Hi guys,

I am working a 2D tile based side scroller and attempting to use a texture atlas as suggested by many here to avoid multiple texture bind calls.  

I was able to fix bleeding using half pixel correction using GL_NEAREST filtering, but I need a fix when using mipmaps.  My issue is that my atlas is tightly packed 32x32 but I want my main character to be scaled to 48x48.  When scaled (either up or down) it looks horrible when using GL_NEAREST so I decided to use mipmaps (GL_LINEAR_MIPMAP_LINEAR) which looks great, but breaks my fix for bleeding.  All of my textures are POT btw.

I have tried google but can't seem to find a fix.  My relevent code is below and I would appreciate any suggestions.

Texture Loader:

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  
52  
53  
54  
55  
56  
   public static Texture loadTexture(String pathToFile)
   {
      int width = 0;
      int height = 0;
      BufferedImage img;
      int[] pixels = null;
      int id = 0;
      ByteBuffer bb = null;
      InputStream is;
     
      try
      {
         is = ResourceManager.class.getClassLoader().getResourceAsStream(pathToFile);
         img = ImageIO.read(is);
         width = img.getWidth();
         height = img.getHeight();
         pixels = img.getRGB(0, 0, width, height, null, 0, width);
         is.close();
         bb = BufferUtils.createByteBuffer((width * height) * 4);
         id = glGenTextures();
         
      } catch (IOException e)
      {
         System.out.println(e.getMessage());
         System.exit(1);
      }
     
      for(int i=0; i<pixels.length; i++)
      {
         byte r = (byte) ((pixels[i] >> 16) & 0xFF);
         byte g = (byte) ((pixels[i] >> 8) & 0xFF);
         byte b = (byte) ((pixels[i]) & 0xFF);
         byte a = (byte) ((pixels[i] >> 24) & 0xFF);
         
         bb.put(r);
         bb.put(g);
         bb.put(b);
         bb.put(a);
      }
     
      bb.flip();
     
      glBindTexture(GL_TEXTURE_2D, id);
     
      glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
      glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL12.GL_CLAMP_TO_EDGE);
      glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL12.GL_CLAMP_TO_EDGE);
      glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, bb);
     
      glBindTexture(GL_TEXTURE_2D, 0);
     
      return new Texture(id,width,height);
   }

SpriteSheet code:

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  
public SpriteSheet(Texture texture, int tileSize)
   {
      this.texture = texture;
      this.tileSize = tileSize;
     
      // Figure out how many texture coordinates we will have
     
      rows = texture.getHeight() / tileSize;
      cols = texture.getWidth() / tileSize;
   
      // Initialize the float buffers
     
      textureCoordinates = new FloatBuffer[rows * cols];
      vertexData = BufferUtils.createFloatBuffer(8);
      vertexData.put(new float[] {0,0,tileSize,0,tileSize,tileSize,0,tileSize});
      vertexData.flip();
     
      // Calculate all the texture coordinates ahead of time
     
      for(int i=0; i<rows; i++)
      {
         for(int j=0; j<cols; j++)
         {
            float srcX = j * tileSize;
            float srcY = i * tileSize;
            float u = (srcX + 0.5f) / texture.getWidth();
            float v = (srcY + 0.5f) / texture.getHeight();
            float u2 = (srcX + tileSize) / texture.getWidth();
            float v2 = (srcY + tileSize) / texture.getHeight();
           
             //displayPosX -= displayPosX%0.1f;
                    //displayPosY -= displayPosY%0.1f;
           textureCoordinates[i * cols + j] = BufferUtils.createFloatBuffer(8);
            textureCoordinates[i * cols + j].put(new float[] {u,v,u2,v,u2,v2,u,v2});
            textureCoordinates[i * cols + j].flip();
         }
      }
     
   }


  
26  Game Development / Shared Code / Re: LWJGL SpriteSheet class on: 2013-08-11 03:50:55
Ok, half pixel correction seemed to cure the problem for me since I'm not using mipmapping.  If anyone is interested this worked for me:

Changed this:
1  
2  
float u = srcX / texture.getWidth();
float v = srcY / texture.getHeight();


To this:
1  
2  
float u = (srcX + 0.5f) / texture.getWidth();
float v = (srcY + 0.5f) / texture.getHeight();


I guess this samples from the center of each texel.  Whew!

Thanks everyone.
27  Game Development / Shared Code / Re: LWJGL SpriteSheet class on: 2013-08-11 03:03:56
Hey guys,

I have rewritten my sprite sheet class based on everyone's suggestions.  It works but I am getting black vertical lines when moving my character but the lines disappear when the character stops.  Any ideas?

Screenshot of issue:



Here is the sprite sheet class:
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  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
package goldenkey.engine;

import static org.lwjgl.opengl.GL11.*;
import java.nio.FloatBuffer;
import org.lwjgl.BufferUtils;

public class SpriteSheet
{
   private Texture texture;
   private FloatBuffer[] textureCoordinates;
   private FloatBuffer vertexData;
   private int tileSize;
   private int rows, cols;
   
   public SpriteSheet(Texture texture, int tileSize)
   {
      this.texture = texture;
      this.tileSize = tileSize;
     
      // Figure out how many texture coordinates we will have
     
      rows = texture.getHeight() / tileSize;
      cols = texture.getWidth() / tileSize;
   
      // Initialize the float buffers
     
      textureCoordinates = new FloatBuffer[rows * cols];
      vertexData = BufferUtils.createFloatBuffer(8);
      vertexData.put(new float[] {0,0,tileSize,0,tileSize,tileSize,0,tileSize});
      vertexData.flip();
     
      // Calculate all the texture coordinates ahead of time
     
      for(int i=0; i<rows; i++)
      {
         for(int j=0; j<cols; j++)
         {
            float srcX = j * tileSize;
            float srcY = i * tileSize;
            float u = srcX / texture.getWidth();
            float v = srcY / texture.getHeight();
            float u2 = (srcX + tileSize) / texture.getWidth();
            float v2 = (srcY + tileSize) / texture.getHeight();
           
            textureCoordinates[i * cols + j] = BufferUtils.createFloatBuffer(8);
            textureCoordinates[i * cols + j].put(new float[] {u,v,u2,v,u2,v2,u,v2});
            textureCoordinates[i * cols + j].flip();
         }
      }
     
   }
   
   public int getTileSize()
   {
      return tileSize;
   }
   
   public void draw(int tileID)
   {
     
      // Draw
     
      glEnableClientState(GL_VERTEX_ARRAY);
      glEnableClientState(GL_TEXTURE_COORD_ARRAY);
     
      glVertexPointer(2, 0, vertexData);
      glTexCoordPointer(2, 0, textureCoordinates[tileID]);
   
      texture.bind();
      glDrawArrays(GL_QUADS, 0, 4);
     
      glDisableClientState(GL_VERTEX_ARRAY);
      glDisableClientState(GL_TEXTURE_COORD_ARRAY);
     
   }
}


I realize that this might not be the right place to post, but I wanted to try to revamp it based on your feedback.
28  Game Development / Shared Code / Re: LWJGL SpriteSheet class on: 2013-08-11 01:12:47
Interesting.  So it sounds like you are saying that the slowdown in the render loop might be worth it then?  I am by no means an expert in OpenGL, so I really appreciate the feedback from more experienced programmers.  I am using vertex arrays by the way because I didn't like the fact that buffers needed to be deleted and the lack of a destructor in Java lol.
29  Game Development / Shared Code / Re: LWJGL SpriteSheet class on: 2013-08-11 00:51:33
I appreciate your feedback, but I prefer this method for a few reasons.  First, it eliminates the need to convert texture coordinates to normalized coordinates in the render loop.  This is especially helpful when using VBO or vertex arrays for rendering because it prevents one from having to update the float buffers constantly.

While I realize that your suggestion is the "usual" approach, the chopping up of the sprite sheet occurs only once and therefore texture coordinates and vertex coordinates need only be initialized one time as well.  However, I would love to see some benchmarking tests using both methods since I strive to keep my code as efficient as possible especially when it comes to rendering.

In regards to the PNGDecoder, I rather enjoyed the challenge and decided to write my own texture loading class which support PNG images.  A good suggestion though for those that would rather not have to write such as a class themselves.

Thanks for reading my post and for your reply!
30  Game Development / Shared Code / LWJGL SpriteSheet class on: 2013-08-08 06:24:05
Hi guys,

I just wanted to share my sprite sheet class that I have been working on in the hopes that it will help someone else.  In essence, it loads an image, crops out each tile into a separate BufferedImage and finally creates a new texture from each sub image.  The id of each "tile" is stored in a 1D array of texture and begins from the first tile and continues to the end of the sheet.

I designed this with RGBA images in mind to support transparency, but it should not be too hard to adapt this to other file formats.

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  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
97  
98  
99  
100  
101  
102  
103  
104  
105  
106  
107  
108  
109  
110  
111  
112  
package goldenkey.engine;

import static org.lwjgl.opengl.GL11.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import javax.imageio.ImageIO;
import org.lwjgl.BufferUtils;

public class SpriteSheet
{
   private Texture[] textures;
   private BufferedImage sheet;
   private int width, height;
   private int tileSize;
   private int rows;
   private int cols;
   
   public SpriteSheet(String pathToFile, int tileSize)
   {
      FileInputStream fis;
      this.tileSize = tileSize;
     
      // Open the file and read in the spritesheet
     
      try
      {
         fis = new FileInputStream(new File(pathToFile));
         sheet = ImageIO.read(fis);
         width = sheet.getWidth();
         height = sheet.getHeight();
         rows = height / tileSize;
         cols = width / tileSize;
         textures = new Texture[rows * cols];
         fis.close();
      }
     
      catch (IOException e)
      {
         System.out.println(e.getMessage());
         System.exit(1);
      }

     
      // Crop out each sub image and create a texture from it
     
      crop();
     
   }
   
   private void crop()
   {
      for(int i=0; i<rows; i++)
      {
         for(int j=0; j<cols; j++)
         {
            BufferedImage temp = sheet.getSubimage(j*tileSize, i*tileSize, tileSize, tileSize);
            int id = generateTexture(temp);
            textures[i * cols + j] = new Texture(id,tileSize,tileSize);
         }
      }
   
   }
   
   private int generateTexture(BufferedImage image)
   {
      int[] pixels = image.getRGB(0, 0, tileSize, tileSize, null, 0, tileSize);
      ByteBuffer bb = BufferUtils.createByteBuffer((tileSize * tileSize) * 4);
      int id = glGenTextures();
     
      for(int i=0; i<pixels.length; i++)
      {
         byte r = (byte) ((pixels[i] >> 16) & 0xFF);
         byte g = (byte) ((pixels[i] >> 8) & 0xFF);
         byte b = (byte) ((pixels[i]) & 0xFF);
         byte a = (byte) ((pixels[i] >> 24) & 0xFF);
         
         bb.put(r);
         bb.put(g);
         bb.put(b);
         bb.put(a);
      }
     
      bb.flip();
     
      glBindTexture(GL_TEXTURE_2D, id);
     
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
      glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
      glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tileSize, tileSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, bb);
     
      glBindTexture(GL_TEXTURE_2D, 0);
     
      return id;
   }
   
   public Texture getTexture(int id)
   {
      if(id < 0 || id >= textures.length) return null;
     
      return textures[id];
   }
   
   public Texture[] getAll()
   {
      return textures;
   }
}


The Texture class is simply a wrapper class containing three fields:  an int containing the texture id and a texture width and height.

I'm posting in the hopes that this will help someone else out there.   Smiley
Pages: [1]
 

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

The first screenshot will be displayed as a thumbnail.

xsi3rr4x (55 views)
2014-04-15 18:08:23

BurntPizza (53 views)
2014-04-15 03:46:01

UprightPath (66 views)
2014-04-14 17:39:50

UprightPath (49 views)
2014-04-14 17:35:47

Porlus (66 views)
2014-04-14 15:48:38

tom_mai78101 (90 views)
2014-04-10 04:04:31

BurntPizza (151 views)
2014-04-08 23:06:04

tom_mai78101 (247 views)
2014-04-05 13:34:39

trollwarrior1 (204 views)
2014-04-04 12:06:45

CJLetsGame (211 views)
2014-04-01 02:16:10
List of Learning Resources
by SHC
2014-04-18 03:17:39

List of Learning Resources
by Longarmx
2014-04-08 03:14:44

Good Examples
by matheus23
2014-04-05 13:51:37

Good Examples
by Grunnt
2014-04-03 15:48:46

Good Examples
by Grunnt
2014-04-03 15:48:37

Good Examples
by matheus23
2014-04-01 18:40:51

Good Examples
by matheus23
2014-04-01 18:40:34

Anonymous/Local/Inner class gotchas
by Roquen
2014-03-11 15:22:30
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!