i have been having trouble trying to set up wraparound in LibGDX using box2D, for example i want my player to appear at the left side of the screen after exiting the right side, but its not working here is my code:
public void setWraparound(){
//if player goes out of bounds vertically
if(body.getPosition().x < 0){
body.setTransform(new Vector2(4.8f, body.getPosition().y),body.getAngle());
}else if(body.getPosition().x > 4.8f){
body.setTransform(new Vector2(0, body.getPosition().y), body.getAngle());
}
//if player goes out of bounds Horizontally
if(body.getPosition().y < 0){
body.setTransform(new Vector2(body.getPosition().x,8f), body.getAngle());
}else if(body.getPosition().y > 8f){
body.setTransform(new Vector2(body.getPosition().x,0), body.getAngle());
}
}
Then i call the method in my GameStage class like this:
public GameStage() {
setUpWorld();
setupCamera();
setupTouchControls();
player.setWraparound();
renderer = new Box2DDebugRenderer();
}
anyone to help me out?
The place where you call your setWraparound method is wrong. You need to call it after a collision of the player with screen border happens. I suggest you do the following
Create static bodies for each screen border (you could use for example EdgeShape for that)
Add a ContactListener to your box2D world and check in the beginContact method if player & wall do touch.
Now after touch was detected call your method setWraparound
Alternatively you could create a Sensor that matches the screen size and detect if player touches the sensor borders. Or you could just check every frame your player's x/y positions and see if they are out of the screen, but it is better to use box2D collision detection.
Related
I'm using the touchDown method (InputProcessor)to move a sprite in the x-axis, i also want it to be moved using the accelerometer.
Is there a way in libGDX to toggle between the two methods and can they both be implemented together (so that the movement is done using the accelerometer as long as the screen is not touched or will they conflict with each other when phone is tilted and screen is touched)
You can do polling.
if (Gdx.input.isTouched()) {
// screen touched logic
} else {
// check for accelerometer
float accelX = Gdx.input.getAccelerometerX();
float accelY = Gdx.input.getAccelerometerY();
float accelZ = Gdx.input.getAccelerometerZ();
// do stuff with the accel(s)
}
I am making a game in which multiple character fire towards each other and on hitting the fire they will act with different animations like: blast, bounce, blur and so on. For now the thing where i am stuck is that while fire is traveling how will we check that its intersecting with other objects of not? I mean run animations only on targeted characters.
You could save your objects that want to check in a vector and schedule an update in your scene that checks if they collide.
This is an answer for Box2D.
Create a body def for each of the objects you are firing. Using some of the code below. Make sure you change shapes to fit what you need. Pixel to meter ratio I set to 32.0 in my code.
b2BodyDef bulletDef;
bulletDef.type = b2_dynamicBody;
bulletDef.position.Set(startPositionX / Pixel_To_Meter_Ratio,
startPositionY / Pixel_To_Meter_Ratio);
auto b2PolygonShape bulletShape;
bulletShape.SetAsBox(bulletWidth / Pixel_To_Meter_Ratio,
bulletHeight / Pixel_To_Meter_Ratio);
auto bulletBody = physicsWorld->CreateBody(bulletDef)
Apply velocity to the body def in the position that you want the bullet to go.
bulletBody->ApplyLinearImpulse(b2Vec(bulletDirectionX,
bulletDirectionY),
physicsBody->GetPosition(),
true);
Add a contact listener to the physics world that inherits from b2ContactListener
// Node that manages the physics world from box2d
class PhysicsNode : public b2ContactListener
{
void BeginContact(b2Contact* contact);
}
// register this listener with the box2d world
auto physicsWorld = new b2World(b2Vec2(0, -9.8f));
physicsWorld ->SetContactListener(this);
Implement the BeginContact function and handle the collision in there.
void PhysicsNode::BeginContact(b2Contact* contact)
{
// Get the physics bodies
auto objectOne = contact->GetFixtureA()->GetBody();
auto objectTwo = contact->GetFixtureB()->GetBody();
// Cast to the type you set as your user data
auto collidableOne = static_cast<Collidable*>(objectOne->GetUserData());
auto collidableTwo = static_cast<Collidable*>(objectTwo->GetUserData());
// Handle your collisions. Apply blur/explode/whatever you need
collidableOne->handleCollision(collidableTwo->isReactableCollision());
collidableTwo->handleCollision(collidableOne->isReactableCollision());
}
I hope this helps. This is what I use to achieve the functionality you are looking for.
I'm trying to implement a collision detector between my Player (Actor) and my Obstacle (Actor too), and I wonder what's the best way to perform a collision detection between them. I see some users saying that they create a Rectangle object in the class and update its bounds every frame, but I don't know if this is the best way to perform this (I'm also trying to make this, but my collision detector method triggers before my Player touches the Obstacle).
This is what I'm trying to check:
public boolean touchedWall() {
// Loop for the obstacles
for (Obstacle obstacle : this.world.getObstacles()) {
// Check if player collided with the wall
if (this.bounds.overlaps(obstacle.getBounds())) {
Gdx.app.log(Configuration.TAG, "collided with " + obstacle.getName());
return true;
}
}
return false;
}
And this is where the method triggers (it should trigger when the Player bounds hit the wall):
I figured out! Instead of using this.bounds.set(x, y, width, height), I was using this.bounds.set(x, y, height, width) like this:
this.bounds.set(this.getX(), this.getY(), this.getHeight(), this.getWidth());
Sorry for my mistake.
I have made an as3 android app where I have used swipe gesture for going next frame and previous frame. but I want when I jump to next or previous frame it swipes smoothly.I have tried to use tween max but it is not working.I have found that tween plugins always work for movie clips.So how can I make the swipe smooth.Can I make it smooth without tween plugins?here is my code....
Multitouch.inputMode = MultitouchInputMode.GESTURE;
stage.addEventListener (TransformGestureEvent.GESTURE_SWIPE, SwipeHandler);
function SwipeHandler(event:TransformGestureEvent):void
{
switch(event.offsetX)
{
// swiped right
case 1:
{
prevFrame();
break;
}
// swiped left
case -1:
{
if(currentFrame == 10)
{
stop();
}
else
{
nextFrame();
break;
}
}
}
}
In order for you to be able to smooth swap you need to have both frames on your screen, which is not the case with genuine Flash frames. Smooth transitions are animated via ENTER_FRAME handlers, with a potential hide of actual frame change process. So, in order to do a smooth transition, you need to move a picture of one frame to the left, and for the other frame to move in from the right instead of plain nextFrame(). Let's say you have a 60fpa stage, and try to smooth transition left. You will need two screen-sized objects, one depicting current frame and one the frame to be displayed, ready to be displayed as a single transition. An example:
var transition:Sprite;
var bitmaps:Array;
var leftSide:Bitmap
var rightSide:Bitmap;
// initialization code, best placed in constructor
leftSide=new Bitmap();
rightSide=new Bitmap();
bitmaps=[];
transition=new Sprite();
transition.addChild(leftSide);
transition.addChild(rightSide);
rightSide.x=stage.stageWidth; //left side and right side should be aside each other
This is the declaration of the needed structures. The plan is to show the transition, giving it two Bitmaps that will be linked to two different BitmapData objects that'll hold pictures of new frame and old frame. We will draw our current frame on current frame's bitmapdata, then take a stored next frame bitmap data and the do transition.
function swipeHandler((event:TransformGestureEvent):void {
var doSwitch:Boolean=false;
var targetFrame:int=currentFrame;
switch(event.offsetX) {
// swiped right
case 1: {
if (currentFrame>2) {
// let's say we're not allowed to swipe right from frame 2
targetframe=currentFrame-1;
doSwitch=true;
}
break;
}
// swiped left
case -1: {
if(currentFrame < 10) {
targetFrame=currentFrame+1;
doSwitch=true;
}
break;
}
}
if (!doSwitch) return;
// prepare transition
if (!bitmaps[targetFrame]) bitmaps[targetFrame]=new BitmapData(stage.stageWidth,stage.stageHeight,false,0xffffff);
// ^ make a new bitmap if there's none for target frame
if (!bitmaps[currentFrame]) bitmaps[currentFrame]=new BitmapData(stage.stageWidth,stage.stageHeight,false,0xffffff);
// the same for source frame
bitmaps[currentFrame].fillRect(bitmaps[currentFrame].rect,0xffffff);
bitmaps[currentFrame].draw(stage); // draw current frame on the bitmap
// with this and stored bitmaps, old frame would remain drawn on the cached bitmap
// and able to be used as a transition image
if (targetFrame>currentFrame) {
leftSide.bitmapData=bitmaps[currentFrame];
rightSide.bitmapData=bitmaps[targetFrame];
transition.x=0;
// here is the place to initialize TweenMax tween to move "transition"
// and don't forget to removeChild(transition) at the end of the tween
} else {
rightSide.bitmapData=bitmaps[currentFrame];
leftSide.bitmapData=bitmaps[targetFrame];
transition.x=-1*stage.stageWidth;
// same here for tweening
}
stage.addChild(transition);
gotoAndStop(targetFrame);
}
This places a prepared transition object on screen above all the underlying items, effectively masking the exact frame switch, done by gotoAndStop() call. This object's x coordinate can be tweened afterwards, and the object should be removed from stage once the tween is ofer.
Hope this helps.
I am beginning to write a game in LibGDX, only just beginning. I have got a basic tile map loaded, a player sprite and can move the character around and the screen (camera) scrolls around - perfect.
I have two overlayed textures in the bottom right of the screen, a left and right arrow, which are used as the joypad to control the character. I position these in relation to the players.x position, which is always fixed to the centre of the screen. Cool so far .... As below:
/////////////////////////////////////////////////////////////////
private void renderJoypad(float deltaTime)
{
batch.draw(Assets.leftJoypad, blockman.position.x-14, 1, 3, 3);
batch.draw(Assets.rightJoypad, blockman.position.x-9, 1, 3, 3);
}
I am now trying to put the player's score in the top left of the screen. The score is made of a Bitmap font, as below.
font = new BitmapFont(Gdx.files.internal("fonts/minecrafter.fnt"),Gdx.files.internal("fonts/minecrafter.png"),false);
font.setScale(0.02f);
In my render() method I cam calling some other methods to update, like the positions of the
leftJoypad etc, as in renderJoypad(). I am also calling my draw font method to update the position of the score, however, when I scroll it is all jerky, and sometimes it shows less characters than there should be.
public void drawScore(float deltaTime)
{
font.draw(batch, "00000", blockman.position.x, 10);
}
I believe that I need to place the score (and any other on screen texts, HUD etc) into a stage, but I cannot understand how to get it working with my existing code.
My show method is as follows:
public void show()
{
//load assets class to get images etc
Assets Assets = new Assets();
//start logging Framerate
Gdx.app.log( GameScreen.LOG, "Creating game" );
fpsLogger = new FPSLogger();
//set the stage - bazinga
Gdx.input.setInputProcessor(stage);
//stage.setCamera(camera);
//stage.setViewport(480, 360, false);
batch = new SpriteBatch();
//load the Joypad buttons
loadJoypad();
//background image
loadBackground();
//sounds
jumpSound = Gdx.audio.newSound(Gdx.files.internal("sounds/slime_jump.mp3"));
//LOAD block man here
// load the map, set the unit scale to 1/16 (1 unit == 16 pixels)
loadMap();
//draw the score
font = new BitmapFont(Gdx.files.internal("fonts/minecrafter.fnt"),Gdx.files.internal("fonts/minecrafter.png"),false);
font.setScale(0.02f);
// create an orthographic camera, shows us 30x20 units of the world
camera = new OrthographicCamera();
camera.setToOrtho(false, 30, 20);
camera.update();
// create the Blockman we want to move around the world
blockman = new Blockman();
blockman.position.set(25, 8);
}
and my render() method is as follows:
public void render(float delta)
{
// get the delta time
float deltaTime = Gdx.graphics.getDeltaTime();
stage.act(deltaTime);
stage.draw();
// clear the screen
Gdx.gl.glClearColor(0.3f, 0.3f, 0.3f, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
renderBackground(deltaTime);
batch = renderer.getSpriteBatch();
//updateBlockman(deltaTime);
blockman.update(deltaTime);
// let the camera follow the blockMan, x-axis only
camera.position.x = blockman.position.x;
camera.update();
// set the tile map rendere view based on what the
// camera sees and render the map
renderer.setView(camera);
renderer.render();
//start the main sprite batch
batch.begin();
// render the blockMan
renderBlockman(deltaTime);
renderJoypad(deltaTime);
drawScore(deltaTime);
batch.end();
fpsLogger.log();
}
I have tried to change the way things work with relation to the Spritebatch etc and just cannot seem to get it working as I require.
Can anyone suggest how I may approach getting a stage and actors to work, or a second camera or something to help me achieve a fixed score display in the corner.
Do I need to use Scene 2D or something - aahhh! My head is exploding....
I look forward and thank you in advance.
Regards
James
I have a couple of suggestions:
Check to see if you have setUseIntegerPositions set to true
(the default) when you draw your font. If you do, and you're scaling
it, then it can cause some odd effects similar to those that you
describe. Set it to false and see if it fixes the problem.
Reset your spritebatch's matrices before drawing the text, that way you won't need to adjust it for the scrolling.
I'd even go as far as to recommend not scaling the font if you can help it, because fonts often look a little odd after being scaled.