Java-Gaming.org Hi !
Featured games (83)
games approved by the League of Dukes
Games in Showcase (539)
Games in Android Showcase (132)
games submitted by our members
Games in WIP (601)
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  
  Resource Loader: Xml loading with filters n' stuff  (Read 3203 times)
0 Members and 1 Guest are viewing this topic.
Offline matheus23

JGO Kernel


Medals: 114
Projects: 3


You think about my Avatar right now!


« Posted 2013-04-05 18:28:35 »

Click to Play
^ preview image ^


The last couple of days and weeks I've been working for some kind of project just for having fun with coding and creating something which is somehow intresting.

It's a resource loader, which can load image sprite sheets and provide cut-out Images after those are loaded. Additionally it allows specifying filters, operating in multiple layers when using filters, etc.

So an xml example would be this one:
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  
<resources>
   <images>
      <image file="sheet.png">
         <!-- Sorcerer -->
         <animation name="sorcerer" delay="0.1">
            <filters>
               <filter name="replace(255, 255, 255, 255 with 1, 1, 1, 0 range 2)" />
               <filter name="colorize_grayscale(0.4, 0.9, 0.3, 1)" />
               <filter name="expand(4, 4)" />
               <filter name="scale(4, 4)" />
               <filter name="voxelize(4, 4 with 0.02, 0.02, 0.02, 1)" />
               <filter name="scale(2, 2)" />
               <filter name="outline(0, 0, 0, 1)" />
               <branch merge="blend(bottom over top)" >
                  <filter name="colorize(0, 0, 0, 1)" />
                  <filter name="blur(8, 8, 16)" />
               </branch>
            </filters>
            <frame bounds="0 0 16 16" />
            <frame bounds="16 0 16 16" />
            <frame bounds="32 0 16 16" />
            <frame bounds="48 0 16 16" />
         </animation>
      </image>
   </images>
</resources>


With an input from this file (scaled 8x):
the outcome of this xml is exactly the image you see above Smiley

So there are two intresting parts in this XML:
  • The <filters></filters>, and
  • The <animation> and <frame />s

The <animation> and <frame />s:

What those do is pretty simple to explain:
In the <animation> tag come the <frame />s. Those frames specify the rectangles for each frame inside the "bounds" tag.
the "name" attribute from the animation tag is a name for the animation, which makes it possible to be referenced from the program.
I won't explain those in great detail. They were the main part of the project at first, but now something else is much more intresting Wink

The <filters></filters>:

I will try to explain those with an example.

We have the source image from above using the same frames and animation as in the xml.

Now what we want is, we want to colorize the image. But only the parts which are grayscale. Additionally we remove the white, opaque pixels in the image and make them white, but transparent. We can do this using two filters:
1  
2  
3  
4  
<filters>
   <filter name="replace(255, 255, 255, 255 with 1, 1, 1, 0 range 2)" />
   <filter name="colorize_grayscale(0.4, 0.9, 0.3, 1)" />
</filters>

Now this animation would be generated (scaled 8x and my application cannot export gif with transparency...):
Click to Play

This is an image which one could use in a game already. But to show you even more advanced filter combinations, and play around a little, and finally also show you how to copy kevglass's voxelization effect (see this thread Wink ), I'll use the "voxelization" filter / effect:
It subtracts the color in a specified grid by a specified ammount:
1  
2  
3  
4  
5  
6  
<filters>
   <filter name="replace(255, 255, 255, 255 with 1, 1, 1, 0 range 2)" />
   <filter name="colorize_grayscale(0.4, 0.9, 0.3, 1)" />
   <filter name="scale(4, 4)" />
   <filter name="voxelize(4, 4 with 0.02, 0.02, 0.02, 1)" />
</filters>


We also scale the image at first to make it possible to create borders around each pixel. Otherwise we couldn't make 4x4 pixel voxels.
The result is this animation:
Click to Play

And since this is not enough. Not even to show all features, I want to 'clone' the Realm of the mad god sprite effects:


As you can see, realm of the mad god sprites have a black outline and a slight black blurred shadowed outline around the characters.
I can recreate this using filters.

First, let's do the black outline. For that I use my 'outline' filter. It creates an outline, which is exactly one pixel wide. We also scale the image again twice, to make the outline a little more subtle:
1  
2  
3  
4  
5  
6  
7  
8  
<filters>
   <filter name="replace(255, 255, 255, 255 with 1, 1, 1, 0 range 2)" />
   <filter name="colorize_grayscale(0.4, 0.9, 0.3, 1)" />
   <filter name="scale(4, 4)" />
   <filter name="voxelize(4, 4 with 0.02, 0.02, 0.02, 1)" />
   <filter name="scale(2, 2)" />
   <filter name="outline(0, 0, 0, 1)" />
</filters>


This is the result (not scaled):
Click to Play

Now we have two problems: How do we add a blurred shadow, and how do we make the sprite bigger, so the shadow (and the outline, too) have place to exist around the sprite?

Well, the solution for the size: expand filter. It adds an empty border to the sprite. I might rename it into 'border' and add some more functionality...
(I won't give an example image here, the result should be clear)

The solution for the shadow is a bit more complicated. For that I use something I call 'branch'.

It works like that:
As soon as my parser encounters a <branch> tag, it saves the old image and proceeds operating on a copy of it. At the end those images are merged together by the specified branch merge operation.

In code this looks like this:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
<filters>
   <filter name="replace(255, 255, 255, 255 with 1, 1, 1, 0 range 2)" />
   <filter name="colorize_grayscale(0.4, 0.9, 0.3, 1)" />
   <filter name="expand(4, 4)" />
   <filter name="scale(4, 4)" />
   <filter name="voxelize(4, 4 with 0.02, 0.02, 0.02, 1)" />
   <filter name="scale(2, 2)" />
   <filter name="outline(0, 0, 0, 1)" />
   <branch merge="blend(bottom over top)" >
      <filter name="colorize(0, 0, 0, 1)" />
      <filter name="blur(8, 8, 16)" />
   </branch>
</filters>


This graph should make the stuff, which is happening clearer:



Click to Play
(scaled 8x)
|
is turned into this,
before it encouters
the <branch> tag:
|
Click to Play
|
Then branching
is going on:
|
/ \
/   \
/     \
/       \
'bottom'        'top'
/           \
/             \
Click to Play
     
Click to Play
\             /
\           /
\         /
\       /
\     /
\   /
\ /
|

merge
(standard blending:
left branch over
right branch)
|
Click to Play

So thats it with the demonstration.
I won't release a demo / the source code yet, since it's not finished. The blur filter is much too inefficient. Still have to optimize it.

I don't think this might be too useful to you. This was more of a project just 4 fun, and probably for the use in some of my games, but it's written in scala, so I guess nobody will want to read the project's source, nor use it, since it's not too nice to use from java Smiley

See my:
    My development Blog:     | Or look at my RPG | Or simply my coding
http://matheusdev.tumblr.comRuins of Revenge  |      On Github
Offline Apex5

Junior Devvie


Medals: 1
Projects: 1



« Reply #1 - Posted 2013-04-05 21:15:21 »

Hehe, had to write my own for last posted wip, had a weird deja vu when I saw this X)
I think the idea of adding filters and properties through the XML is really cool though; also the shadow is looking awesomes!
Considering porting it to Java as a library? :3 /glee
Offline Danny02
« Reply #2 - Posted 2013-04-05 22:29:52 »

@Apex5 no need to port anything, you can just use scala from java
@matheus23 using your lib with a scala DSL would be nice, also just upload it on github Cheesy

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline matheus23

JGO Kernel


Medals: 114
Projects: 3


You think about my Avatar right now!


« Reply #3 - Posted 2013-04-06 08:41:37 »

@Danny I think Apex talked about it not being useable really nicely from the side of java. Something like you'd have to write method$less$greater method names, but the library actually works well, if you don't want to write your own filters ^^. But you have to write your own backend if you want to use it with OpenGL (that is: LWJGL) or LibGDX or similar, but that should be trivial 2 classes.

This is how the interface you'd have to use looks like:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
trait ResourceLoader[I <: Image[I,_],L] {

  protected val regions = new mutable.HashMap[String, I]()
  protected val animations = new mutable.HashMap[String, AnimationData[I]]()

  def region(name: String) = regions.get(name) match {
    case Some(region) => region
    case None => throw new IllegalArgumentException("There is no region available for the name \""+name+"\"")
  }
  def animation(name: String) = animations.get(name) match {
    case Some(anim) => anim
    case None => throw new IllegalArgumentException("There is no animation available for the name \""+name+"\"")
  }

  def allAnimations = animations
  def allRegions = regions

  def load(loadingSource: L, directory: File)
}


Also, to make some updates, I've made the library reasonable fast. It has now an implementation for my so-called 'native filters'. These are filters the implementation / backend implement. So you could implement a blurring algorithm running with shaders on the gpu, instead of the CPU. That's almost how I implemented a faster blur algorithm. The blur doesn't take 1600 ms for a 80x80, but actually only takes 4 ms. This was quite a satisfying number Wink

I'll upload the source on github, when I've got the demo ready Smiley

See my:
    My development Blog:     | Or look at my RPG | Or simply my coding
http://matheusdev.tumblr.comRuins of Revenge  |      On Github
Offline sproingie

JGO Kernel


Medals: 202



« Reply #4 - Posted 2013-04-06 15:50:51 »

1  
2  
3  
4  
  def region(name: String) = regions.get(name) match {
    case Some(region) => region
    case None => throw new IllegalArgumentException("There is no region available for the name \""+name+"\"")
  }


Pretty sure you can express this pattern with this:

1  
2  
3  
  def region(name: String) : I = regions.getOrElse(
    name, throw new IllegalArgumentException(s"There is no region available for the name \"$name\"")
  )


I did add the return type since I suspect it won't infer anything from the exception (haven't tested it), and I also threw in a string interpolation for free  Kiss
Offline matheus23

JGO Kernel


Medals: 114
Projects: 3


You think about my Avatar right now!


« Reply #5 - Posted 2013-04-06 16:11:37 »

Pretty sure you can express this pattern with this:

1  
2  
3  
  def region(name: String) : I = regions.getOrElse(
    name, throw new IllegalArgumentException(s"There is no region available for the name \"$name\"")
  )


I also threw in a string interpolation for free  Kiss

Oh yes, I know... I've used it later in my learning progress, this was the first (or second) class I made in this project, when I almost didn't know scala...  persecutioncomplex
Didn't know the string interpolation though... (strange name)

To provide a further update:
It's now possible to define groups of filters:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
<resources>
   <filters>
      <!-- Realm of the mad god filter -->
      <filtergroup name="rotmg">
         <filter name="expand(4, 4)" />
         <filter name="scale(8, 8)" />
         <filter name="outline(2 with 1, 1, 1, 1)" />
         <filter name="outline(1 with 0, 0, 0, 1)" />
         <branch merge="blend(bottom over top)" >
            <filter name="colorize(0, 0, 0, 1)" />
            <filter name="fastblur(16)" />
         </branch>
      </filtergroup>
   </filters>
   [...]


which can then be later referenced from the animations and regions:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
   [...]
   <images>
      <image file="sheet.png">
         <!-- Sorcerer -->
         <animation name="sorcerer" delay="0.1">
            <filters>
               <filter name="replace(255, 255, 255, 255 with 1, 1, 1, 0 range 2)" />
               <filter name="colorize_grayscale(0.4, 0.9, 0.3, 1)" />
               <filtergroup name="rotmg" />
            </filters>
            <frame bounds="0 0 16 16" />
            <frame bounds="16 0 16 16" />
            <frame bounds="32 0 16 16" />
            <frame bounds="48 0 16 16" />
         </animation>
      </image>
   </images>
</resources>


<edit>
You ninja'd me! Cheesy
I did add the return type since I suspect it won't infer anything from the exception (haven't tested it)
No, should be okay...
<edit>
Well, the right version is this one:
1  
2  
  def region(name: String) = regions.get(name).getOrElse(
    throw new IllegalArgumentException("There is no region available for the name \"$name\""))

infers, does everything one wants.
</edit>
</edit>

See my:
    My development Blog:     | Or look at my RPG | Or simply my coding
http://matheusdev.tumblr.comRuins of Revenge  |      On Github
Offline sproingie

JGO Kernel


Medals: 202



« Reply #6 - Posted 2013-04-07 15:09:25 »

Yah the get then getOrElse will also work.  Basically, pattern-matching on Option is an antipattern to avoid.

http://blog.tmorris.net/posts/scalaoption-cheat-sheet/
(need JS on, the link is broken without it)

Actually a for-comprehension over Either would be ideal for this but Scala's Either is kind of broken as a monad.  Scalaz has a Validation type that's pretty nifty though, you just have to deal with Scalaz's general lack of documentation Tongue

https://gist.github.com/oxbowlakes/970717
Offline matheus23

JGO Kernel


Medals: 114
Projects: 3


You think about my Avatar right now!


« Reply #7 - Posted 2013-04-07 18:12:13 »

@sproingie

Yep. Already seen Scalaz. Pretty sure I'll use it Smiley Head of it having state-monads implemented. I really think this is an awesome piece of science.
The problem I have with those is only that they're not really needed in a non-pure-functional language. And it's sad that JVM can't handle pure functionality.

Also, thank you very much for the links Smiley

Anyways,

I've uploaded the project to github ^^ This is the link:
https://github.com/matheus23/AnimationLoader

The code is probably not readable at all... Well, if you put some time into it. But the most ugly class is 'org.matheusdev.animationSwing.AnimationTester', which is the test class for viewing animations and exporting them to .gif's. It's incredibly ugly.
Yes. It's a single file.

Also, have a look at the other classes inside 'org.matheusdev.animationSwing' (SwingImge, SwingImageLoader), to see how easy it is to write backends for my lib Smiley

See my:
    My development Blog:     | Or look at my RPG | Or simply my coding
http://matheusdev.tumblr.comRuins of Revenge  |      On Github
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.

rwatson462 (30 views)
2014-12-15 09:26:44

Mr.CodeIt (20 views)
2014-12-14 19:50:38

BurntPizza (42 views)
2014-12-09 22:41:13

BurntPizza (76 views)
2014-12-08 04:46:31

JscottyBieshaar (37 views)
2014-12-05 12:39:02

SHC (51 views)
2014-12-03 16:27:13

CopyableCougar4 (48 views)
2014-11-29 21:32:03

toopeicgaming1999 (115 views)
2014-11-26 15:22:04

toopeicgaming1999 (103 views)
2014-11-26 15:20:36

toopeicgaming1999 (30 views)
2014-11-26 15:20:08
Resources for WIP games
by kpars
2014-12-18 10:26:14

Understanding relations between setOrigin, setScale and setPosition in libGdx
by mbabuskov
2014-10-09 22:35:00

Definite guide to supporting multiple device resolutions on Android (2014)
by mbabuskov
2014-10-02 22:36:02

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
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!