Creating an animated cloud creature

Started by pigoto, June 01, 2013, 08:10:49 PM

Previous topic - Next topic

pigoto

Hello all!

Just a quick intro as I'm new here:

I'm a software developer (.NET and other languages - 7 years experience) and I've been playing around with Android for about a year, and recently got into 3D-game development with JPCT-AE. I've messed around with the Hello World app and read the wiki.

I understand the basic theory of game development (I know what a mesh, vertices and game loop are for example).

I'm here to just hopefully get pointed in the right direction on some things as I like to learn whilst doing rather than reading.

My first question - I want to create an animated, colourful cloud in JPCT-AE that moves around the screen - this cloud is more of a character than a cloud in the sky. i.e. a colourful bit of smoke that whizzes around the screen. No face or  specific shape required though.

Could someone point me in the right direction to create this? Should I create a 3DS model of this or are there some particle classes I should look into?

Really just an overview is all I need, but any code samples appreciated.

EgonOlsen

...it depends...do you have an image or a simple drawing to show exactly what you mean!?

pigoto

Hi, thanks for the reply. I did a quick search in Google to find roughly what I'm thinking:

http://www.secondpicture.com/tutorials/digital_image_processing/smoke_effect_in_photoshop.jpg

It would look a bit like this, be centered in a white screen, and would be 3D and move around. Hope that gives a clearer idea.

pigoto

ok I think I can be more specific now after playing around a bit. I've experimented with JPCT-AE and I think the best way to achieve what I'm after would be some sort of particle system.

I attempted to create this a 3DS model, but I want it to have a fluid animation. Not sure if you know the smoke monster from lost, but I guess I want it to kind of move around like that.

I may be wrong but I think a particle system would be best for this (rather than an animated 3DS model). I'm open to correction though, but any code samples or further info on creating a particle system would be great. :-)

EgonOlsen

I'm not sure if a particle system is needed for this. Some textured quads with a smoke texture and bill boarding enabled that somehow move around a little might to the job.

pigoto

Thanks - I've done some searching on those terms and found this post which looks like it will be useful - it discusses a bomb blast with similar concepts and has a code sample so I think this will get me started:

http://www.jpct.net/forum2/index.php?topic=1620.0

I'll post up some code when I get it working.

pigoto

Ok I've used that explosion example, and created the below code, at the moment it just creates a stack of smoke squares going into the screen.

My aim is to create a load of these smoke squares (64 at the moment), disperse them all to create one cloud, then loop through each one in the game loop and translate to move the entire cloud. This seems inefficient though as I'll have a large loop in every game loop..

.. am I anywhere near or heading in completely the wrong direction?


import java.lang.reflect.Field;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import com.threed.jpct.Camera;
import com.threed.jpct.FrameBuffer;
import com.threed.jpct.Light;
import com.threed.jpct.Logger;
import com.threed.jpct.Object3D;
import com.threed.jpct.Primitives;
import com.threed.jpct.RGBColor;
import com.threed.jpct.SimpleVector;
import com.threed.jpct.Texture;
import com.threed.jpct.TextureManager;
import com.threed.jpct.World;
import com.threed.jpct.util.BitmapHelper;
import com.threed.jpct.util.MemoryHelper;

import android.app.Activity;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.view.MotionEvent;

public class Monster extends Activity {
private static Monster master = null;

private GLSurfaceView mGLView;
private MyRenderer renderer = null;
private FrameBuffer fb = null;
private World world = null;
private RGBColor back = new RGBColor(255, 255, 255);

private static Object3D cloudpiece = null;
private Object3D[] cloud = new Object3D[64];

private int fps = 0;
private long lastRun = 0;

private Light sun = null;

protected void onCreate(Bundle savedInstanceState) {
if (master != null) {
copy(master);
}

super.onCreate(savedInstanceState);
mGLView = new GLSurfaceView(getApplication());

renderer = new MyRenderer();
mGLView.setRenderer(renderer);
setContentView(mGLView);
}

@Override
protected void onPause() {
super.onPause();
mGLView.onPause();
}

@Override
protected void onResume() {
super.onResume();
mGLView.onResume();
}

@Override
protected void onStop() {
super.onStop();
}

private void copy(Object src) {
try {
Logger.log("Copying data from master Activity!");
Field[] fs = src.getClass().getDeclaredFields();
for (Field f : fs) {
f.setAccessible(true);
f.set(this, f.get(src));
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}

public boolean onTouchEvent(MotionEvent me) {

try {
Thread.sleep(15);
} catch (Exception e) {
// No need for this...
}

return super.onTouchEvent(me);
}

class MyRenderer implements GLSurfaceView.Renderer {

private long time = System.currentTimeMillis();

public MyRenderer() {

}

public void onSurfaceChanged(GL10 gl, int w, int h) {
if (fb != null) {
fb.dispose();
}
fb = new FrameBuffer(gl, w, h);

if (master == null) {

world = new World();
world.setAmbientLight(20, 20, 20);

sun = new Light(world);
sun.setIntensity(250, 250, 250);

addTextures();
configureCloudPieces();
createCloud();

//Add to world
for (int i = 0; i < cloud.length; i++) {
world.addObject(cloud[i]);
}

//Center on "middle" cloud piece
Camera cam = world.getCamera();
cam.moveCamera(Camera.CAMERA_MOVEOUT, 50);
cam.lookAt(cloud[cloud.length / 2].getTransformedCenter());

SimpleVector sv = new SimpleVector();
sv.set(cloud[cloud.length / 2].getTransformedCenter());
sv.y -= 100;
sv.z -= 100;
sun.setPosition(sv);
MemoryHelper.compact();

if (master == null) {
master = Monster.this;
}
}
}

private void addTextures() {
Texture redsmoke = new Texture(BitmapHelper.rescale(BitmapHelper.convert(getResources().getDrawable(R.drawable.texture_redsmoke)), 64, 64));
TextureManager.getInstance().addTexture("redsmoke", redsmoke);

Texture bluesmoke = new Texture(BitmapHelper.rescale(BitmapHelper.convert(getResources().getDrawable(R.drawable.texture_bluesmoke)), 64, 64));
TextureManager.getInstance().addTexture("bluesmoke", bluesmoke);

Texture greensmoke = new Texture(BitmapHelper.rescale(BitmapHelper.convert(getResources().getDrawable(R.drawable.texture_greensmoke)), 16, 16));
TextureManager.getInstance().addTexture("greensmoke", greensmoke);
}

private void configureCloudPieces() {
cloudpiece = Primitives.getPlane(1, 3);
cloudpiece.setTexture("redsmoke");
cloudpiece.setBillboarding(true);
cloudpiece.setTransparency(2);
//cloudpiece.setAdditionalColor(java.awt.Color.WHITE);
cloudpiece.getMesh().compress();
cloudpiece.build();
}

private void createCloud() {
int x = 1;
int y = 1;
int z = 1;

for (int i = 0; i < cloud.length; i++) {
cloud[i] = new Object3D(cloudpiece);
cloud[i].translate(x, y, z);
x = x + 1;
y = y + 1;
z = z + 1;
}
}

public void onSurfaceCreated(GL10 gl, EGLConfig config) {
}

public void onDrawFrame(GL10 gl) {
if (System.currentTimeMillis() - lastRun >= 80) {

lastRun = System.currentTimeMillis();
}

fb.clear(back);
world.renderScene(fb);
world.draw(fb);
fb.display();

if (System.currentTimeMillis() - time >= 1000) {
Logger.log(fps + "fps");
fps = 0;
time = System.currentTimeMillis();
}
fps++;
}
}

}




[attachment deleted by admin]

EgonOlsen

I would give it a try that way. I'm not convinced that you really need 64 planes to make this look good though, which might be a bit heavy indeed.