I was just wondering, if you want to create an object for a game, lets say a ball,
Should you create a class called ball that it contains the sprite and the body?, like:
public class Ball {
BaseGameActivity mActivity;
Sprite s;
Body mBody
public Ball(TextureRegion texture,BaseGameActivity mActivity){
this.mActivity=mActivity;
s= new Sprite (0,0,texture,mActivity.getVertexBufferObjectManager());
mBody=PhysicsFactory.createBoxBody(mActivity.mWorld,s, BodyDef.BodyType.StaticBody,PhysicsFactory.createFixtureDef(1,0,2));
//then it shoud be properly attached to scene and world etc...
}
}
A class that extends sprite? like:
public class Ball extends Sprite {
BaseGameActivity mActivity;
Body mBody
public Ball(TextureRegion texture,BaseGameActivity mActivity){
super (0,0,texture,mActivity.getVertexBufferObjectManager());
this.mActivity=mActivity;
mBody=PhysicsFactory.createBoxBody(mActivity.mWorld,this, BodyDef.BodyType.StaticBody,PhysicsFactory.createFixtureDef(1,0,2));
//then it shoud be properly attached to scene and world etc...
}
}
Or another way?
Which is the fastest? Which is the easier? Or the way doesn't matter?
Thanks in advance
just do like this.. u will probably need other sprites and other stuff...
public class Ball extends BaseGameActivity{
//constructor and other methods
BitmapTextureAtlas ballAtlas;
ITextureRegion ballTexture;
//in onLoadResources load ur atlas
//create texture region
//then in onCreateScene create a scene
//simply attach ur sprite ball to ur scene
}
you can create sprites anywhere.. you are not bound to create separate class for that
I think you can use both approach, it depends on you and your coding style / application infrastructure. :)
Altough I use a generic SceneManager class with a reference to the activity, instead of multiple activities
Related
I have the following (simplified) rig so far:
MyActivity.java:
public class MyActivity extends Activity {
public GLSurfaceView myGLView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myGLView = new MyGLSurfaceView(this);
setContentView(myGLView);
}
}
MyGLSurfaceView.java:
public class MyGLSurfaceView extends GLSurfaceView {
private MyRenderer mMyRenderer = new MyRenderer();
private MyThread mMyThread = new MyThread();
public MyView(Context context) {
super(context);
setRenderer(mGameRenderer);
setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
mGameThread.setRunning(true);
}
}
MyRenderer.java:
public class GameRenderer implements GLSurfaceView.Renderer {
#Override
public void onDrawFrame(GL10 gl) {
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
// ...
}
}
MyThread.java:
Here I'm doing all initializations, creating objects and so on.
public class MyThread extends Thread {
private MyObject mMyObject = new MyObject();
public MyThread {
// ...
mMyObject.setRot();
this.start();
}
public void run() {
// Fixed Timestep Loop goes here
mMyObject.getRot();
}
}
MyObject.java:
This is a sample object which holds different fileds and methods.
public class MyObject {
private double mRot;
// Getters & Setters
protected double getRot() { return mRot; }
protected void setRot() {
// ... Do calculations
}
public void draw() {
// OGL Instructions go here
gl.glRotatef(1.2f, 0, 0, setRot());
}
}
Now the problem I was running into is the following: (I guess, I missed something very basic and simple :) )
As stated above, I'm creating my object instances in the MyThread class. The Thread is created in the MyGLSurface class, same goes for the Renderer. Now, that I have that two threads I can't figure out, how to use that one instance and their methods in that two separate threads.
I tried different approaches, but nothing did work. So in my opinion I made a mistake in the class design. I mean, I don't just want to get it running (that'd be quite easy), but I want to know how to do it correctly.
The main problem is actually that I can't access the MyObject's instance and simply use the draw() method in the renderer - because I don't get it.
I thought, it would be possible to call the draw() method of MyObject within the rendering thread without the need of using a singleton and so on. So simply referencing the instance to it. But somehow that seemed weird and dirty (besides that it doesn't work for me).
I tried dozens of different approaches, but I really need a bump into the right direction. I'm quite familar with OOP, but here I might really miss something.
In that many samples I found on the web (stackoverflow, Replica Island, different tutorial sites, Google I/O, DevCentral, etc.) they either didn't use a multithreaded system or they split it directly (GL objects from regular objects).
Any hint into the right direction would be much appreciated!
Another example to peruse:
https://code.google.com/p/android-breakout/
The wiki and code comments discuss the threading issues inherent in using GLSurfaceView. In particular, the game does as much setup as it can before the Renderer thread starts; once it's running, as much work as possible is done on that thread. The game state objects are effectively "owned" by the renderer thread, and the Activity is owned by the UI thread, so any "off-thread" interactions are handled by sending messages rather than making direct method calls. For example, see the handling of touch events.
It's good that you're thinking about this -- you either need synchronization or careful object discipline to avoid nasty race conditions.
See also: android game loop vs updating in the rendering thread
The nice thing about GLSurfaceView is that it creates the OpenGL rendering thread for you, so you don't need to create one yourself. The main UI thread will call the OnDraw() method in your view class and that's all the threads you need. If you really want to create your own thread for OpenGL rendering, use TextureView instead of GLSurfaceView. Here is an article that I think will help:
http://software.intel.com/en-us/articles/porting-opengl-games-to-android-on-intel-atom-processors-part-1
The Setup : A RelativeLayout with a GLSurfaceView and a Button as shown in the image..
The Problem: Lets say I have other triangle models (The one in the picture being the initial model)... I wish to change the models cyclically on click of the button. Since button is on the UI thread and glSurfaceView runs on a separate thread, I don't exactly know how to pass the info/instruction to it. I know there is this thing called Handler in Android which might be useful in this case... But I need some help here..
Edit: If Handler is the right way, I need to know how to add Looper to that Handler... The documentation says add looper.prepare() at the start of run() method.. But the glSurfaceView creates thread implicitly, resulting in no run() method directly available..
I don't think it is necessary to use handlers to solve this issue but you may need to adjust the way you organise your classes.
Here is an example of an organisational structure that might solve your issue:
Activity Class
public class MainActivity extends Activity {
private int modelNumber = 0;
private ArrayList<Model> models = new ArrayList<Model>();
private YourRendererClass renderer;
#Override
public void onCreate(Bundle savedInstanceState) {
...
// Setup GLSurfaceView
GLSurfaceView surface = new GLSurfaceView(this);
setContentView(surface);
renderer = new YourRendererClass();
surface.setRenderer(renderer);
// Set up models
models.add(new Model(x, y, size etc..));
models.add(new Model(x, y, size etc..));
models.add(new Model(x, y, size etc..));
etc.
// Display first model
renderer.setCurrentModel(models.get(modelNumber));
...
}
// Called by the button press:
// Use android:onClick="onClick"
// in your layout xml file within button
public void onClick(View view){
// Make it loop round
modelNumber++;
if(modelNumber>=models.size()){
modelNumber=0;
}
// Display current model
renderer.setCurrentModel(models.get(modelNumber));
}
}
Renderer Class
public class YourRendererClass implements Renderer {
private Model currentModel;
#Override
public void onDrawFrame(GL10 gl) {
// ** Your existing set-up code **//
// Draw model
if (currentModel!=null){
currentModel.draw(gl);
}
}
public void setCurrentModel(Model model){
currentModel = model;
}
}
Model class
public class Model {
// Holds model information
private int size;
private int x;
private int y;
// etc...
public model(int x, int y, int size etc...){
this.x=x;
this.y=y;
this.size=size;
// etc....
}
public void draw(GL10 gl) {
// ** Draw model based on model information fields above **
}
}
The above code is untested as I don't have access to your drawing code but the structure should work if implemented correctly. I've tried to make it clear where you'll have to insert your own code to make it work. In particular I wasn't sure what defines each of your different models so you'll need to include sufficient local variables within the Model class to define them.
I hope my answer helps, let me know if you have any questions.
Tim
You should look at queueEvent! It's a very convenient way to pass informations from UI Thread to renderer Thread:
queueEvent(new Runnable(){
#Override
public void run() {
mRenderer.method();
}});
I can get the scene from a layer, but I don't know how to have a Scene that manages layers. I can do this on iPhone, but on Android my code doesn't even get called.
This is in my start Activity:
CCDirector.sharedDirector().runWithScene(EditorScene.node());
This is my scene class:
public class EditorScene extends CCScene
{
public EditorScene()
{
CanvasBackgroundLayer canvasBackgroundLayer = (CanvasBackgroundLayer) CanvasBackgroundLayer.node();
CanvasEditorLayer canvasEditorLayer = (CanvasEditorLayer) CanvasEditorLayer.node();
addChild(canvasBackgroundLayer,0);
this.addChild(canvasEditorLayer);
}
}
My constructor here is never called. Any ideas on what to do?
Any subclasses of CCScene have to reimplement the static method node(). Have a look at the bottom of CCScene.h.
Can any one sort the problem in the code..i.e "The constructor CCSprite(String) is not visible".All the required imports have been imported, i have commented the error on the specified line where it is anoying me. thanks in advance
public class Sprite extends CCLayer{
CCSprite mSprite;
protected Sprite() {
super();
CGSize winSize = CCDirector.sharedDirector().winSize();
mSprite =new CCSprite("sprite.png");//Error:The constructor CCSprite(String) is not visible
mSprite.setPosition(CGPoint.ccp(mSprite.getContentSize().width/2.0f, mSprite.getContentSize().height/2.0f));
addChild(mSprite);
}
}
The exception message is telling you that the constructor you call here is not visible, i.e. it is private or has package visibility. Are you sure the source you looked at is the source you are calling?
I am making an application for android which could grow somewhat large over time. What I would like to do is implement into the main class sub files for logic. For example:
The main activity uses a surfaceview.
class Battle extends SurfaceView implements SurfaceHolder.Callback {
I want to add all logic related to touch events in a file called touchActions.java
public class touchActions extends Battle {
It appears to work fine with no errors in Eclipse. But when I try to run it on my phone, I get a null pointer exception for the following line.
if (_touch.checkHitBox(1)) {
_touch being initiated after the Battle class is declared.
public touchActions _touch;
What is the proper way to do this, or what could be causing the nullpointerexception?
EDIT:
The goal here is organization of code, so that I don't end up with one gigantic file of code. Can I make an inner class while still using a different file? If you know of a tutorial, that would be great too.
_touch being initiated after the Battle class is declared.
public touchActions _touch;
not initiated ... just declared u need to initiatie it with something like this
_touch = new touchActions();
EDIT:
if public touchActions _touch; is declared in Battle class you do it all wrong ...
it should be something like this
class Battle extends SurfaceView implements SurfaceHolder.Callback {
public touchActions _touch;
public Battle (){
_touch = new touchActions(this);
_touch.callingMethodFromTouch();
}
}
//should not extends Battle
public class touchActions {
Battle parent_;
public touchActions (Battle parent){
parent_ = parent;
}
.... rest of implemetation you can call parent_.methodFromBattleClass(); here
}