Java-Gaming.org    
Featured games (81)
games approved by the League of Dukes
Games in Showcase (492)
Games in Android Showcase (112)
games submitted by our members
Games in WIP (556)
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  
  libGDX: Draw a wavy background  (Read 1428 times)
0 Members and 1 Guest are viewing this topic.
Offline devmas

Senior Newbie


Projects: 1



« Posted 2013-04-17 04:44:02 »

Here is code to make a static picture a wavy background.

A video of what I mean:
http://www.youtube.com/watch?v=HmnEnl0_mr4MmB9b5njVbA

I don't know if there's a better name for it, but basically, it's an effect used in various old video games. The effect worked either scanline based if the hardware supported it (e.g. Game Boy) or simply by sliding the tile rows back and forth. It was often used in lava scenes (to show heat) or underwater scenes.

I wanted to use that effect in my game, so I came up with this code. I have a small feeling that this effect is actually really easy to code, but I was a bit proud when I did it. :p It may be useful to someone, so I'm sharing it.

Usage:
1. Instantiate the BGWave with the file name of the background pic you want to wave (pic should be close to the same resolution as the screen)
2. update() every frame.
3. render() every draw.
4. Remember to dispose() the background texture when you're finished with it.

You may change the field variables to tweak the wave to your liking. Here is a picture describing what the field variables do:



The code itself:

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  
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Texture;

public class BGWave {

   //The background texture
  Texture bg;
   
   //the screen resolution. Update this every frame if you allow screen resizing
  int hres = 640;
   int vres = 480;
   
   //the number of segments on the screen. The higher the number, the better quality
  //the wave looks, but the more polys drawn. Max value is the vertical screen resolution.
  int segments = 32;
   
   //distance wave will travel (be pushed) left/right
  float cycstrength = 16;
   
   //number of complete wave cycles on screen
  float numcycles = 2;
   
   //speed wave will cycle
  float cyclespeed = 1/numcycles;
   
   //the current position of the wave cycle
  float cycoffset = 0;
   
   
   /** Creates the wave background, loading the background texture into memory */
   BGWave(String filename) {
      bg = new Texture(Gdx.files.internal(filename));
   }
   
   
   /** Update the wave by increasing the position of the wave cycle by the speed */
   void update() {
      //make sure you update the resolution (hres/vres) every frame
     // if you expect the screen to be resized
     cycoffset += cyclespeed;
   }
   
   /** Render the wavy background */
   void render() {
     
      //scale the image so that the background image touches the window with no black borders
     float bgscale = hres/(float)bg.getWidth();
      float temp = vres/(float)bg.getHeight();
      if (temp > bgscale) bgscale = temp;
     
      //For reference, here's how you'd draw the background normally, no wave
     /*
      batch.draw(bg,
            GameMain.hres/2-(bg.getWidth()*bgscale)/2,
            GameMain.vres/2-(bg.getHeight()*bgscale)/2,
            bg.getWidth()*bgscale,
            bg.getHeight()*bgscale);
      */

     
      //size of segment on screen
     float segmentSize = vres/(float)segments;
      //size of segment in the picture to draw
     float picSegSize = (segmentSize/bgscale);
      float picYBorder = ((((bg.getHeight()*bgscale)-vres)/2)/bgscale)*1.5f;
     
     
      for (int i = 0; i < segments; i++) {
         batch.draw(bg,
               hres/2-(bg.getWidth()*bgscale)/2 + (pos(i*segmentSize)), //x
              i*segmentSize,                                           //y
              bg.getWidth()*bgscale,                                   //width
              segmentSize,                                             //height
             
               0,                                                       //picture x
              (int) (bg.getHeight()-picYBorder-(picSegSize*i)-picSegSize), //pic y
              bg.getWidth(),                                           //pic wid
              (int)picSegSize,                                         //pic hei
              false,false);
      }
     
   }
   
   /** returns the amount the wave should be pushed left/right in the given position */
   float pos(float num) {
      num += cycoffset;
      return (float) (Math.sin(num*(Math.PI*2/vres)*numcycles)) * cycstrength;
   }

}


Enjoy! Use it as you like.

Room for improvement:
- don't use quads for each segment, use triangles to make parallelograms (it still looks good with quads, though).
Offline R.D.

Senior Member


Medals: 2
Projects: 1


"For the last time, Hats ARE Awesome"


« Reply #1 - Posted 2013-04-17 22:45:39 »

This could be done with a small shader. Something like this:

vert:
1  
2  
3  
4  
5  
6  
7  
// Simple vertex shader
// only maps the verticies to the correct position in the matrix

void main() {
   gl_TexCoord[0] = gl_MultiTexCoord0;
   gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;  
}


frag:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
uniform float time;       
uniform float speed;      
uniform vec2 amplitude;      
uniform vec2 frequence;      
uniform sampler2D texture;    

const float pi = 3.14159;

void main()
   vec2 uv = gl_TexCoord[0].xy;
   vec2 temp = vec2(uv.x, uv.y);
   
   float angularFre = 2.0 * pi * frequence.x;
   uv.x += sin(temp.y * angularFre  + (time * (speed * 10.0))) * ((amplitude.x) / texsize.x) * 10.0;
   
   vec4 color = texture2D(texture, uv);

    gl_FragColor = color;
}


Noooot tested. You need to change for libgdx a bit (and changed the magic numbers maybe).
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.

Nickropheliac (15 views)
2014-08-31 22:59:12

TehJavaDev (23 views)
2014-08-28 18:26:30

CopyableCougar4 (33 views)
2014-08-22 19:31:30

atombrot (41 views)
2014-08-19 09:29:53

Tekkerue (40 views)
2014-08-16 06:45:27

Tekkerue (35 views)
2014-08-16 06:22:17

Tekkerue (25 views)
2014-08-16 06:20:21

Tekkerue (37 views)
2014-08-16 06:12:11

Rayexar (72 views)
2014-08-11 02:49:23

BurntPizza (49 views)
2014-08-09 21:09:32
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!