I’m trying to develop a very simple game for Android using libgdx: there is a bug that appears randomly on the screen and you have to touch it where the bug is to kill it. If you do, the game goes on until you miss three times, and then is game over. Simple enough.
So, I see the bug, I touch it right in the middle, but I miss: the touch point isn’t included in the bug rectangle, which is different from what I see on the screen. I print out the coordinates of both rectangle and point and I see that those of the rectangle were correct a couple of deltaTimes ago, but are no longer, despite of what I see on the screen. I have looked all over the place for a solution, read tutorials, libgdx documentation, but I don’t get it, I'm getting nuts.
This is the code for the touchDown event on the constructor
Gdx.input.setInputProcessor(new InputAdapter(){
#Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
unidadTiempo = unidadTiempo - aceleracion;
toque.set(screenX, screenY, 0f);
camara.unproject(toque);
if (bicho.contains(toque.x, toque.y)) {
aplastamiento.play();
bichosLiquidados++;
} else {
burla.play();
vidas--;
}
return true;
}
});
This is the method drawing the bugs and accelerating the bug appearing pace
void apareceBicho(){
ultimoBicho = TimeUtils.nanoTime();
juego.letra.draw(juego.batch, "Puntuacion: " + bichosLiquidados, 0, altoPantalla);
bicho.setX(xAleatorio);
bicho.setY(yAleatorio);
juego.batch.draw(bichoImagen, bicho.x, bicho.y);
while (TimeUtils.nanoTime() - ultimoBicho < unidadTiempo && vidas > 0){
unidadTiempo = unidadTiempo - aceleracion;
xAleatorio = MathUtils.random(randomx);
yAleatorio = MathUtils.random(randomy);
}
if(vidas == 0){
risa.play();
TextureRegion fotogramActual = animacionFinal.getKeyFrame(stateTime, true);
juego.batch.draw(fotogramActual, bicho.x, bicho.y);
juego.batch.flush();
gameover = true;
}
if (gameover){
juego.setScreen(new PantallaFinal(juego, this));
}
}
And lastly, the render method
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0.2f, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stateTime += Gdx.graphics.getDeltaTime();
camara.update();
juego.batch.setProjectionMatrix(camara.combined);
juego.batch.begin();
juego.batch.draw(yerbita, 0, 0, anchoPantalla, altoPantalla);
apareceBicho();
juego.batch.end();
}
This is what I meant by a couple of deltaTimes ago:
06-04 09:30:05.942 RECTANGLE POSITION AIMED TO: Posicion del bicho: 612.88776, 200.9191, 133.0, 126.0
06-04 09:30:07.950 ACTUAL RECTANGLE POSITION: Posicion del bicho: 426.92572, 111.10537, 133.0, 126.0
06-04 09:30:09.946 TOUCH POSITION: Coordenadas toque = 659.2, 250.3111
Possible reason :
bicho having zero width and height.
If you created rectangle by default constructor then need to be set width and hight of that rectangle.
bicho = new Rectangle();
bicho.setSize(bichoImagen.getWidth(),bichoImagen.getHeight());
Im new on Box2d got a problem and couldnt solve it.
I want to move my player left and right when the user touch my left and right buttons.
I created a fixture I can move body and fixture but not the player sprite
How can I attach my player sprite to my body ?
and How should I control body because I cant stop it.
I want to find a proper way of controlling player in box2d. I couldnt use setLinerVelocity etc.
this is my codes
public World world;
public Body bplayer;
public Box2DDebugRenderer b2dr;
public Matrix4 cameraBox2D;
PlayScreen
buttonimage.addListener(new ClickListener() {
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button)
{
bplayer.setLinearVelocity(-5*PPM , 0);
return true;
}
});
world = new World(new Vector2(player.getPosition().x , player.getPosition().y) , false);
b2dr = new Box2DDebugRenderer();
bplayer = createPlayer(player.getPosition().x , player.getPosition().y);
show method
buttonimage.setPosition(160,0);
rightbuttonimage.setPosition(320,0);
pauseimage.setPosition(220,-20);
cameraBox2D = camera.combined.cpy();
Render method
Gdx.gl.glClearColor(0, 0, 2f, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
sb.setProjectionMatrix(camera.combined);
player.position.y += 500 * Gdx.graphics.getDeltaTime();
sb.begin();
sb.draw(bg, 0, camera.position.y - (camera.viewportHeight/2));
sb.draw(player.sprite, player.getPosition().x , player.getPosition().y);
for (Tube tube : tubes) {
sb.draw(tube.getlefttube(), tube.getposlefttube().x, tube.getposlefttube().y);
sb.draw(tube.getrighttube(), tube.getposrighttube().x, tube.getposrighttube().y);
sb.draw(tube.getLight() , tube.getPoslight().x , tube.getPoslight().y);
}
delta*=speed;
sb.end();
update(delta);
b2dr.render(world , cameraBox2D);
stage.draw();
app.batch.begin();
app.font23.draw(app.batch,"Lights collected :" + dropsGathered , 0, 720);
app.batch.end();
cameraUpdate method
Vector3 position = camera.position;
position.x = player.position.x;
position.y = player.position.y;
camera.position.set(position);
createPlayer method
Body pBody;
BodyDef def = new BodyDef();
def.type = BodyDef.BodyType.DynamicBody;
def.position.set(x * PPM, y * PPM );
def.fixedRotation = true;
pBody = world.createBody(def);
return pBody;
update method
world.step(1 / 60f , 6 , 2);
for(int i = 0; i < tubes.size; i++) {
Tube tube = tubes.get(i);
if (camera.position.y - (camera.viewportWidth/2) > tube.getposlefttube().y + tube.getlefttube().getWidth()) {
tube.reposition(tube.getposlefttube().y + ( TUBE_COUNT) );
}
if (tube.collides(player.getBounds())){
app.setScreen(new GameOver(app));
}
if (tube.gathered(player.getBounds())){
dropsGathered++;
}
if (dropsGathered >= 50){
//app.setScreen(new Stage2(app));
}
}
camera.update();
handleInput();
camera.position.y = player.getPosition().y + 300;
player.update(delta);
camera.update();
cameraUpdate(delta);
stage.act(delta);
Do not use the Sprite class. Use the TextureRegion class instead. Sprite is confusingly subclassed from TextureRegion, so when you call batch.draw(sprite, ...) its position and rotation parameters are ignored because it is being treated as a TextureRegion.
You could use a Sprite by calling sprite.draw(batch) but a Sprite is redundant because your Body already has position and rotation parameters.
Use a TextureRegion directly with the SpriteBatch. You can orient it with rotation parameters passed into the draw method.
I am developing a game in AndEngine and I want to attach a sprite to a parallax background (on my main menu) BUT I don't want the sprite to be repeated (which is what is currently happening).
I have tried this (below) which works but I use the sprites in the game so when I come back to the main menu, the sprites will have moved (I tried resetting the sprites but doesn't seem to be working).
Sprite playerCar = new Sprite(playerX, playerY,
mResourceManager.mPlayerCarTextureRegion,
mVertexBufferObjectManager);
playerCar.setRotation(-15);
attachChild(playerCar);
What I want to do is the following:
Define my sprite as normal:
Sprite playerCar = new Sprite(playerX, playerY,
mResourceManager.mPlayerCarTextureRegion,
mVertexBufferObjectManager);
playerCar.setRotation(-15);
Then attach it to my background:
ParallaxBackground menuParallaxBackground = new ParallaxBackground(0,
0, 0);
menuParallaxBackground.attachParallaxEntity(new ParallaxEntity(0,
new Sprite(0, SCREEN_HEIGHT
- mResourceManager.mParallaxLayerRoad.getHeight(),
mResourceManager.mParallaxLayerRoad,
mVertexBufferObjectManager)));
menuParallaxBackground.attachParallaxEntity(new ParallaxEntity(0,
playerCar));
Which also works but the car keeps on repeating which I do not want.
Any help would be appreciated! Thanks.
Problem was because of the onDraw method on the ParallaxEntity class in the ParallaxBackground class. There was a loop around where the sprites get drawn that keeps going until the sprites fill up the width of the screen. I simply created a custom class and removed the while loop so I could use it for my Main Menu.
ParallaxEntity onDraw code before:
public void onDraw(final GLState pGLState, final Camera pCamera, final float pParallaxValue) {
pGLState.pushModelViewGLMatrix();
{
final float cameraWidth = pCamera.getWidth();
final float shapeWidthScaled = this.mAreaShape.getWidthScaled();
float baseOffset = (pParallaxValue * this.mParallaxFactor) % shapeWidthScaled;
while(baseOffset > 0) {
baseOffset -= shapeWidthScaled;
}
pGLState.translateModelViewGLMatrixf(baseOffset, 0, 0);
float currentMaxX = baseOffset;
do {
this.mAreaShape.onDraw(pGLState, pCamera);
pGLState.translateModelViewGLMatrixf(shapeWidthScaled, 0, 0);
currentMaxX += shapeWidthScaled;
} while(currentMaxX < cameraWidth);
}
pGLState.popModelViewGLMatrix();
}
my CustomParallaxEntity onDraw code after (notice the last while loop removed):
public void onDraw(final GLState pGLState, final Camera pCamera,
final float pParallaxValue) {
pGLState.pushModelViewGLMatrix();
{
final float shapeWidthScaled = this.mAreaShape.getWidthScaled();
float baseOffset = (pParallaxValue * this.mParallaxFactor)
% shapeWidthScaled;
while (baseOffset > 0) {
baseOffset -= shapeWidthScaled;
}
pGLState.translateModelViewGLMatrixf(baseOffset, 0, 0);
this.mAreaShape.onDraw(pGLState, pCamera);
pGLState.translateModelViewGLMatrixf(shapeWidthScaled, 0, 0);
}
pGLState.popModelViewGLMatrix();
}
Thanks to the comments on my question for helping me figure out a solution.
I am using the libgdx framework and trying to repeat a background of spikes forever. The issue I am having is that the texture is moving extremely fast forever, but I want to slow it down. I was looking at a tutorial from Google Code and another user had this same issue. The "supposed" solution was this:
if(scrollTimer>1.0f)
scrollTimer = 0.0f;
scrollTimer = 3f;
This was to make it scroll 3 times faster, so I attempted this and substituted 0.3f instead of 3f, but this makes the background at a standstill.
Here is some relevant code that might help in solving this issue:
public class PlayScreen implements Screen{
final Rectangle upSpikeBounds = new Rectangle(0,0,Gdx.graphics.getWidth() * 2, 25);
final Rectangle downSpikeBounds = new Rectangle(0,Gdx.graphics.getHeight() - 25,Gdx.graphics.getWidth() * 2, 25);
Rectangle blockBounds;
float total_time = 0f;
Sprite spikeUpSprite, spikeDownSprite, spriteBlock;
public PlayScreen(Game game){
batch = new SpriteBatch();
player = new Player(new Vector2(Gdx.graphics.getWidth()/10, Gdx.graphics.getHeight()/2), batch);
stage = new Stage();
this.game = game;
Texture spikeUp = new Texture(Gdx.files.internal("spikes.png"));
Texture spikeDown = new Texture(Gdx.files.internal("spikes.png"));
spikeUp.setWrap(TextureWrap.Repeat, TextureWrap.Repeat);
spikeDown.setWrap(TextureWrap.Repeat, TextureWrap.Repeat);
spikeUpSprite = new Sprite(spikeUp, 0, 0, Gdx.graphics.getWidth(), 25);
spikeDownSprite = new Sprite(spikeDown, 0, 25, Gdx.graphics.getWidth(), -25);
spikeDownSprite.setPosition(0, Gdx.graphics.getHeight() - 20);
spikeUpSprite.setSize(1200, 25);
spikeDownSprite.setSize(1200, 25);
}
public void render(float deltaTime) {
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
label.setText("Score: " + player.score);
cam.position.set(player.getPosition().x + Gdx.graphics.getWidth()/2,Gdx.graphics.getHeight () / 2,0);
batch.setProjectionMatrix(cam.combined);
cam.update();
total_time += Gdx.graphics.getDeltaTime();
if (total_time > 1.0f){
total_time = 0.0f;
}
spikeUpSprite.setU(total_time);
spikeUpSprite.setU2((total_time+1));
spikeDownSprite.setU(total_time);
spikeDownSprite.setU2(total_time+1);
stage.act();
batch.begin();
spikeUpSprite.draw(batch);
spikeDownSprite.draw(batch);
batch.end();
stage.draw();
}
}
Can anyone help me?
You should look up the tween engine, it will enable you to use 'tween animation', which is an animation of values, who with a duration. For instance if you animate from zero to 700 with a 700ms duration, the value will start from zero and increase by 1 every ms
While micnubinub's answer is certainly interesting and worth checking out, I have figured out a quick fix for my issue. The problem lies in this line:
total_time += Gdx.graphics.getDeltaTime();
This is where the speed of the background lies. Because delta time is so fast (probably to the microsecond), the background scrolls by too fast. If I change it to a manual number, such as 0.0093f, I get a background that scrolls at the speed I desire.
I have been creating meshes using equations, but applying texture seems to be an issue.
I have created a cube and cylinder but when texture is applied, the texture is not getting allocated and only the object is visible. I created a Cylinder successfully with the help of this link - How to make a cylinder in renderscript and I've created a cube of my own. The 2 objects are visible, but not the texture applied on them. I'm able to allocate textures only for my a3d objects that I've created, but not for the meshes created using equations. Any ideas where I'm going wrong? Please suggest what could be the problem, or is it not possible to apply texture for such meshes?
my CustomShaders that im using are shaderv.glsl and shaderf.glsl - same as what is there in the examples
public Mesh cubeMesh(float ltf, float lbf, float rbf, float rtf, float ltb, float lbb, float rbb, float rtb){
Mesh.TriangleMeshBuilder mbo= new TriangleMeshBuilder(mRSGL,3, Mesh.TriangleMeshBuilder.TEXTURE_0);
//front
mbo.setTexture(0, 0);
mbo.addVertex(-lbf, -lbf,lbf); //lbf
mbo.setTexture(1, 0);
mbo.addVertex( rbf, -rbf,rbf); //rbf
mbo.setTexture(1, 1);
mbo.addVertex( rtf, rtf, rtf); //rtf
mbo.setTexture(0, 1);
mbo.addVertex(-ltf, ltf, ltf); //ltf
//top
mbo.setTexture(0, 0);
mbo.addVertex(-ltf, ltf,ltf); //ltf
mbo.setTexture(1, 0);
mbo.addVertex(rtf, rtf,rtf); //rtf
mbo.setTexture(1, 1);
mbo.addVertex(rtb, rtb,-rtb); //rtb
mbo.setTexture(0, 1);
mbo.addVertex(-ltb, ltb,-ltb); //ltb
//back
mbo.setTexture(0, 0);
mbo.addVertex(rbb, -rbb,-rbb); //rbb
mbo.setTexture(1, 0);
mbo.addVertex(-lbb, -lbb,-lbb); //lbb
mbo.setTexture(1, 1);
mbo.addVertex(-ltb, ltb,-ltb); //ltb
mbo.setTexture(0, 1);
mbo.addVertex(rtb, rtb,-rtb); //rtb
//bottom
mbo.setTexture(0, 0);
mbo.addVertex(-lbb, -lbb,-lbb); //lbb
mbo.setTexture(1, 0);
mbo.addVertex(rbb, -rbb,-rbb); //rbb
mbo.setTexture(1, 1);
mbo.addVertex(rbf, -rbf,rbf); //rbf
mbo.setTexture(0, 1);
mbo.addVertex(-lbf, -lbf,lbf); //lbf
//left
mbo.setTexture(0, 0);
mbo.addVertex(-lbb, -lbb,-lbb); //lbb
mbo.setTexture(1, 0);
mbo.addVertex(-lbf, -lbf,lbf); //lbf
mbo.setTexture(1, 1);
mbo.addVertex(-ltf, ltf,ltf); //ltf
mbo.setTexture(0, 1);
mbo.addVertex(-ltb, ltb,-ltb); //ltb
//right
mbo.setTexture(0, 0);
mbo.addVertex(rbf, -rbf,rbf); //rbf
mbo.setTexture(1, 0);
mbo.addVertex(rbb, -rbb,-rbb); //rbb
mbo.setTexture(1, 1);
mbo.addVertex(rtb, rtb,-rtb); //rtb
mbo.setTexture(0, 1);
mbo.addVertex(rtf, rtf,rtf); //rtf
mbo.addTriangle(0,1,2);//1
mbo.addTriangle(2,3,0);
mbo.addTriangle(4,5,6);//2
mbo.addTriangle(6,7,4);
mbo.addTriangle(8,9,10);//3
mbo.addTriangle(10,11,8);
mbo.addTriangle(12,13,14);//4
mbo.addTriangle(14,15,12);
mbo.addTriangle(16,17,18);//5
mbo.addTriangle(18,19,16);
mbo.addTriangle(20,21,22);//6
mbo.addTriangle(22,23,20);
return mbo.create(true);
}
private Mesh cylinder(){
float radius=1.25f, halfLength=5;
int slices=16;
Mesh.TriangleMeshBuilder mbo= new TriangleMeshBuilder(mRSGL,3, Mesh.TriangleMeshBuilder.TEXTURE_0);
/*vertex at middle of end*/
mbo.addVertex(0.0f, halfLength, 0.0f);
mbo.addVertex(0.0f, -halfLength, 0.0f);
for(int i=0; i<slices; i++) {
float theta = (float) (i*2.0*Math.PI / slices);
float nextTheta = (float) ((i+1)*2.0*Math.PI / slices);
/*vertices at edges of circle*/
mbo.addVertex((float)(radius*Math.cos(theta)), halfLength, (float)(radius*Math.sin(theta)));
mbo.addVertex((float)(radius*Math.cos(nextTheta)), halfLength, (float)(radius*Math.sin(nextTheta)));
/* the same vertices at the bottom of the cylinder*/
mbo.addVertex((float)(radius*Math.cos(nextTheta)), -halfLength, (float)(radius*Math.sin(nextTheta)));
mbo.addVertex((float)(radius*Math.cos(theta)), -halfLength, (float)(radius*Math.sin(theta)));
/*Add the faces for the ends, ordered for back face culling*/
mbo.addTriangle(4*i+3, 4*i+2, 0);
//The offsets here are to adjust for the first two indices being the center points. The sector number (i) is multiplied by 4 because the way you are building this mesh, there are 4 vertices added with each sector
mbo.addTriangle(4*i+5, 4*i+4, 1);
/*Add the faces for the side*/
mbo.addTriangle(4*i+2, 4*i+4, 4*i+5);
mbo.addTriangle(4*i+4, 4*i+2, 4*i+3);
}
return mbo.create(true);
}
public void initMesh(){
m1= cubeMesh(1,1,1,1,1,1,1,1);
mScript.set_gCubeMesh(m1); //cube
m2 = cylinder();
mScript.set_gCylinder(m2); //Cylinder
}
and I'm loading the texture initially like this:
private void loadImages() {
cubetex = loadTextureRGB(R.drawable.crate);
cylindertex = loadTextureRGB(R.drawable.torusmap);
mScript.set_cubetex(cubetex);
mScript.set_gTexCylinder(cylindertex);
}
and in the rs side the cube and cylinder functions that are called by the root:
static void displayCustomCube()
{
// Update vertex shader constants
// Load model matrix
// Apply a rotation to our mesh
gTorusRotation += 50.0f * gDt;
if (gTorusRotation > 360.0f)
{
gTorusRotation -= 360.0f;
}
// Setup the projection matrix
if(once<1)
{
float aspect = (float)rsgGetWidth() / (float)rsgGetHeight();
rsMatrixLoadPerspective(&gVSConstants->proj, 40.0f, aspect, 0.1f, 1000.0f);
once++;
}
// Position our model on the screen
rsMatrixLoadTranslate(&gVSConstants->model, 0,2,-10);
setupCustomShaderLights();
rsgBindProgramVertex(gProgVertexCustom);
// Fragment shader with texture
rsgBindProgramStore(gProgStoreBlendNoneDepth);
rsgBindProgramFragment(gProgFragmentCustom);
rsgBindSampler(gProgFragmentCustom, 0, gLinearClamp);
rsgBindTexture(gProgFragmentCustom, 0, cubetex);
// Use no face culling
rsgBindProgramRaster(gCullNone);
rsgDrawMesh(gCubeMesh); // load cube model
}
static void displayCustomCylinder()
{
// Update vertex shader constants
// Load model matrix
// Apply a rotation to our mesh
gTorusRotation += 50.0f * gDt;
if (gTorusRotation > 360.0f)
{
gTorusRotation -= 360.0f;
}
// Setup the projection matrix
if(once<1)
{
float aspect = (float)rsgGetWidth() / (float)rsgGetHeight();
rsMatrixLoadPerspective(&gVSConstants->proj, 40.0f, aspect, 0.1f, 1000.0f);
once++;
}
// Position our model on the screen
rsMatrixLoadTranslate(&gVSConstants->model, 0,2,-10);
setupCustomShaderLights();
rsgBindProgramVertex(gProgVertexCustom);
// Fragment shader with texture
rsgBindProgramStore(gProgStoreBlendNoneDepth);
rsgBindProgramFragment(gProgFragmentCustom);
rsgBindSampler(gProgFragmentCustom, 0, gLinearClamp);
rsgBindTexture(gProgFragmentCustom, 0, gTexCylinder);
// Use no face culling
rsgBindProgramRaster(gCullNone);
rsgDrawMesh(gCylinder); // load cylinder model
}
definition of setCustomShaderLights() is:
static void setupCustomShaderLights()
{
float4 light0Pos = {xLight0Pos, yLight0Pos, zLight0Pos, aLight0Pos};
float4 light1Pos = { 0.0f, 0.0f, 20.0f, 1.0f};
float4 light0DiffCol = {xDiffColLight0, yDiffColLight0, zDiffColLight0, aDiffColLight0};
float4 light0SpecCol = {xSpecColLight0, ySpecColLight0, zSpecColLight0, aSpecColLight0};
float4 light1DiffCol = {0.5f, 0.5f, 0.9f, 1.0f};
float4 light1SpecCol = {0.5f, 0.5f, 0.9f, 1.0f};
gLight0Rotation += 50.0f * gDt;
if (gLight0Rotation > 360.0f)
{
gLight0Rotation -= 360.0f;
}
gLight1Rotation -= 50.0f * gDt;
if (gLight1Rotation > 360.0f)
{
gLight1Rotation -= 360.0f;
}
// Set light 0 properties
gVSConstants->light0_Posision = light0Pos;
gVSConstants->light0_Diffuse = DiffLight0Val;
gVSConstants->light0_Specular = SpecLight0Val;
gVSConstants->light0_CosinePower = Light0Cos;
// Set light 1 properties
gVSConstants->light1_Posision = light1Pos;
gVSConstants->light1_Diffuse = 1.0f;
gVSConstants->light1_Specular = 0.7f;
gVSConstants->light1_CosinePower = 25.0f;
rsgAllocationSyncAll(rsGetAllocation(gVSConstants));
// Update fragmetn shader constants
// Set light 0 colors
gFSConstants->light0_DiffuseColor = light0DiffCol;
gFSConstants->light0_SpecularColor = light0SpecCol;
// Set light 1 colors
gFSConstants->light1_DiffuseColor = light1DiffCol;
gFSConstants->light1_SpecularColor = light1SpecCol;
rsgAllocationSyncAll(rsGetAllocation(gFSConstants));
}
and loadTextureRGB() is:
private Allocation loadTextureRGB(int id)
{
return Allocation.createFromBitmapResource(mRSGL, mRes, id,
Allocation.MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE,
Allocation.USAGE_GRAPHICS_TEXTURE);
}
Texturing these meshes is definitely possible. It likely isn't the only solution to your problem, but one reason you are not getting any texturing of the cylinder is that you never declare texture coordinates for that mesh when you create it. You are for the cube though so just transfer that method over. As for why the texture is not showing up, I don't see anything immediately wrong with your code. What is the GLSL code for your custom shaders? Is it the same as from the MiscSamples example? What about your definition for setupCustomShaderLights() and loadTextureRGB()? Are they also the same from the example code?