Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1410890 Posts in 69591 Topics- by 58581 Members - Latest Member: elpoeprod

October 09, 2024, 05:37:30 AM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsCommunityDevLogsGrapple - Android 2D platformer (released to Google Play!)
Pages: [1] 2 3
Print
Author Topic: Grapple - Android 2D platformer (released to Google Play!)  (Read 11744 times)
bornander
Level 1
*



View Profile WWW
« on: December 08, 2014, 01:35:42 PM »

Finally done:


The game is free, has no ads nor any in-game purchases and I would very much like to hear any comments you might have.

Grapple trailer:




Update:

I've got a (very) pre-alpha desktop version available for download here; https://drive.google.com/uc?id=0B38R323dMc0oWWtheDU0WjEzd28&export=download

Controls are W, A, S, D and clicking with the mouse in the direction you want to fire the grappling hook (when you find that, you start without it). The game is not really intended for desktop play so things like changing window size isn't handled properly. Further, most levels aren't finished and the game is missing most levels.

If anyone is willing to try it I would be interested to know if this is a game you would want play to completion (considering it will be an Android game with just 32 levels and be free and free from ads), any feedback is greatly appreciated.



Hi all,

In an attempt to learn libGDX (http://libgdx.badlogicgames.com/) I have decided to try to make a 2D platformer for Android using Box2D. I used Box2D for my Hovercraft game (http://forums.tigsource.com/index.php?topic=43833) and I really liked it and one thing I missed with AndEngine that I used for that project is the lack of cross-platform support, something that libGDX seems to be better at.

I have a sped-up video showing some early game-play here:


I am basing my method for using Box2D on this (fairly old article); http://www.badlogicgames.com/wordpress/?p=2017. But I changing the structure of the avatar to be built from to circles rather than a rectangle and a circle. I think that will fit better and also allow me to have collisions with the torso/head that don't look to weird.

Here's a debug-render of me testing jumping;


The head/torso and legs/feet circles are two fixture that I add to the same body;

Code:
private static Fixture getBodyFixture(final Body body) {
final CircleShape shape = new CircleShape();
shape.setRadius(0.505f);

final FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = shape;
fixtureDef.density = 0.64f;
fixtureDef.filter.categoryBits = PhysicsConstants.CATEGORY_PLAYER;
fixtureDef.filter.maskBits = PhysicsConstants.MASK_PLAYER;

final Fixture fixture = body.createFixture(fixtureDef);
fixture.setFriction(0.0f);
shape.dispose();
return fixture;
}

private static Fixture getFeetFixture(final Body body) {
final CircleShape shape = new CircleShape();
shape.setRadius(0.45f);
shape.setPosition(new Vector2(0, -0.55f));
final FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = shape;
fixtureDef.density = 0.64f;
fixtureDef.filter.categoryBits = PhysicsConstants.CATEGORY_PLAYER;
fixtureDef.filter.maskBits = PhysicsConstants.MASK_PLAYER;

final Fixture fixture = body.createFixture(fixtureDef);
fixture.setFriction(1.0f);

shape.dispose();
return fixture;
}

The head/torso is friction-less as that prevents the player from getting stuck when close to walls.

I haven't really figured out much of the game-mechanics yet but I know I want to incorporate a grappling-hook, and because I am not good at level design my levels won't be "puzzly".

I am using the TileD editor for the level creation, on my last project I wrote the level editor from scratch and while that had some advantages it reallt hampered me when it came to creating well balanced levels.

It's probably a bad idea starting a dev-blog for a project I'll only be able to work on on my commute to/from work just before christmas, but I need something to push me to finish this.

On the short term to-do list I have;

  • Grappling-hook, I will try to implement this using a series of rope-joints.
  • Avatar sprites, I will have to get these from somewhere as I can't do graphics myself.
  • Terrain sprites, I am going to use a tile map for the levels (and, again, I need to get these as I can't do graphics).

I've got a sprite sheet I saw on opengameart.org in mind, hopefully it will suit my need.
« Last Edit: September 16, 2015, 09:50:24 PM by bornander » Logged

Current devlog; Grapple
Try Hovercraft for Android, voted "a game" by players.Hovercraft on Google play
bornander
Level 1
*



View Profile WWW
« Reply #1 on: December 09, 2014, 12:37:33 PM »

So using a tilesheet I found on opengameart I've manage to render the terrain. The only annoying/tedious part was taking the spritesheet split it up into individual tiles only to merge them back into a new tilesheet with padding to avoid texture-bleed (it feels like something libGDX should do for me when loading the textures rather than at build-time using tools).

Using the TileD editor to design the levels is easy and I am beginning to realize just how much time I've wasted on previous projects building my own tools.

My levels use 4 tile layers, one of which is the layer used for the parallax-scroll effect. I achieve that effect by rendering the parallax layer using a camera that snaps to the "actual" camera with a scale on the horizontal axis;

Code:

private void updateParallaxCamera(final OrthographicCamera mainCamera) {
  parallaxLayerCamera.setToOrtho(false, mainCamera.viewportWidth, mainCamera.viewportHeight);
  parallaxLayerCamera.position.set(mainCamera.position);
  updateCamera(parallaxLayerCamera, 0.75f);
}

private void updateCamera(final OrthographicCamera camera, final float scale){
  final float tx = player.getPosition().x;
  final float ty = player.getPosition().y;
       
  final float halfHeight = camera.viewportHeight / 2.0f;
  final float halfWidth = camera.viewportWidth / 2.0f;

  camera.position.x = Math.min(Math.max(camera.zoom * halfWidth, tx), mapSize.x - halfWidth) * scale;
  camera.position.y = Math.min(Math.max(camera.zoom * halfHeight, ty), mapSize.y - halfHeight);

  camera.update();
}

public void draw(final OrthographicCamera camera) {
  updateCamera(camera, 1.0f);
  updateParallaxCamera(camera);

  ...

  mapRenderer.setView(parallaxLayerCamera);
  mapRenderer.render(PARALLAX_LAYERS);
  mapRenderer.setView(camera);
  mapRenderer.render(BACKGROUND_LAYERS);

  ...
}


I decided to implement the grappling-hook like this;

  • 1. Spawn a fix number of small, circular bodies close together.
  • 2. Connect the bodies using rope-joints, with the first body being connected to the player body.
  • 3. Give all bodies a velocity in the direction the grappling-hook should fire, scaled by index in the series of bodies (so closest to the player gets least velocity).
  • 4. Use a contact listener to listen for contacts between the last body and any terrain body, and if found; create a rope joint to the terrain body.

I used Box2D category masks for filtering the collisions, when the "rope" of the grappling-hook was allowed to collide with itself the results were peculiar so I prevent that by only allowing the hook to collide with the terrain.

It's working well but I suspect I need alot of tuning to get it just right;


Next task will be rendering the player and making him animated.
Logged

Current devlog; Grapple
Try Hovercraft for Android, voted "a game" by players.Hovercraft on Google play
oahda
Level 10
*****



View Profile
« Reply #2 on: December 09, 2014, 12:40:48 PM »

Oh, I was going to implement almost just that in Box2D like tonight. Shocked Thank you for the instructions! I'll try to put it to use!
Logged

bornander
Level 1
*



View Profile WWW
« Reply #3 on: December 10, 2014, 12:40:45 AM »

Oh, I was going to implement almost just that in Box2D like tonight. Shocked Thank you for the instructions! I'll try to put it to use!

One thing you might want to keep in mind; I had to make the bodies making up the "links" of the rope very light (almost zero mass), or the momentum built up when firing the grappling-hook would pull the player along when the rope was fully extended. There was a lot of tweaking to get it right.
Logged

Current devlog; Grapple
Try Hovercraft for Android, voted "a game" by players.Hovercraft on Google play
oahda
Level 10
*****



View Profile
« Reply #4 on: December 10, 2014, 01:30:43 AM »

Yeah, since mine isn't going to be the exact same thing and be used exactly like that and have more uses, I'll imagine I'll have to do even more tweaking and adjustments, but I'm still grateful for this great foundation! Looks slick in your gif there, so hopefully this will turn into a neat game!
Logged

bornander
Level 1
*



View Profile WWW
« Reply #5 on: December 10, 2014, 12:26:51 PM »

So the sprite sheets I use for the terrain also had a character sprite-set in the same pack (which is Buch's "A Platformer in the Forest", by the way) and it has three diffent characters; Naked, Green Link-like and a King. So my game is going to be about a king whose clothes and crown has been stolen (which is why you'll start out naked in the game).

Creating animations in libGDX was easy, it's essentially a matter of doing this (with most animations left out);

Code:
public class CharacterState {

public final TextureRegion walk_0;
public final TextureRegion walk_1;
public final TextureRegion walk_2;
public final TextureRegion walk_3;

public final Animation walkRightAnimation;

public CharacterState(final TextureAtlas atlas, final String name) {
walk_0 = find(atlas, name, "0");
walk_1 = find(atlas, name, "1");
walk_2 = find(atlas, name, "2");
walk_3 = find(atlas, name, "3");

walkRightAnimation = new Animation(0.2f, walk_0, walk_1, walk_2, walk_3);
walkRightAnimation.setPlayMode(PlayMode.LOOP);
        }
}

The bigger problem was figuring out when each animation is applicable. This seemed fairly straight-forward at first but got more complicated when I did the swinging-from-a-grappling-hook and standing-on-a-platform-going-east-whilst-looking-west animations.

In any case, the Naked animation looks like this;

And this is the Link-like one;


And I realize I need to get better at making smaller .gif files, I'll try to keep the size down in the future.

Next to implement will be the doors. You're going to be free to pick the level to play and you pick by walking up to and entering a door in the level-select level. Then you'll have a limited amount of time to complete the level and get back out before the door shuts.
Logged

Current devlog; Grapple
Try Hovercraft for Android, voted "a game" by players.Hovercraft on Google play
bornander
Level 1
*



View Profile WWW
« Reply #6 on: December 11, 2014, 02:13:38 PM »

I'm too lazy to get a proper animation of a door opening so when my avatar enters a door I settled for simply replacing the closed-door tiles with some open-door tiles. Changing tiles in a TMX tile map in libGDX can be done either by having the tiles animated and starting the animation or by simply changing the tile data for the affected cell, I went with the latter option.
Code:
final Cell ct = new Cell();
final Cell cb = new Cell();
final TiledMapTileSet tileSet = map.getTileSets().getTileSet("tileset");
ct.setTile(tileSet.getTile(130));
cb.setTile(tileSet.getTile(147));
layer.setCell((int)bounds.x, (int)bounds.y + 1, ct);
layer.setCell((int)bounds.x, (int)bounds.y    , cb);
Using hardcoded magic values like 130 and 147 is of course not super-bright but I am ignoring that fact for now.


To get the guy to kind of walk off into the distance I simply scale down the sprite whilst lowering the alpha channel.

When time runs out in a level in my game the door was supposed to be locked, but instead of changing it to a locked version I got side-tracked by the libGDX particle editor and decided to set the door on fire instead (as you do) as a way of preventing the user from using the door. It was way more fun and it made me feel like Tom Hanks in Castaway when manages to create fire  Who, Me?


Next task will be implementing damage, so that the player will die if he falls from too high up or indeed gets caught in a door-fire.
Logged

Current devlog; Grapple
Try Hovercraft for Android, voted "a game" by players.Hovercraft on Google play
oahda
Level 10
*****



View Profile
« Reply #7 on: December 11, 2014, 10:08:01 PM »

Too lazy to animate a door, but not to set up a particle fire, eh? c;
I have to say you seem rather quick and efficient at adding new stuff, tho. Things are shaping up quickly here.

Maybe you could just try to programmatically animate the door's horizontal scale from 1 to 0.1 or something while darkening it a bit. That might be enough to make it look like it's swinging open.
Logged

bornander
Level 1
*



View Profile WWW
« Reply #8 on: December 12, 2014, 03:47:43 AM »

Too lazy to animate a door, but not to set up a particle fire, eh? c;
Particle systems were surprisingly simple in libGDX, essentially all I had to do was;
Code:
fireEffect.load(Gdx.files.internal("effects/fire.p"), atlas);
...
fireEffect.draw(batch, elapsed);
And the .p file was generated using a tool where I could visually design my fire. And the tool starts up with a fire as it's default effect Smiley.

I have to say you seem rather quick and efficient at adding new stuff, tho. Things are shaping up quickly here.
Thank you! Although progress might be a bit misleading. I am doing this on my work commute and I feel I need to finish a task each day, but that sometime means hurrying up to complete something before the train pulls into the station. My code, whilst kind-of working, suffers from it;
Code:
if (isEnteringDoor()) {
  animation = Assets.instance.characters.getDefault().climbAnimation;
  final float scale = (0.5f / Level.TILE_SIZE) + 0.5f * (1.0f / Level.TILE_SIZE) * (1.0f - currentDoor.getEnterFraction());
  sprite.setScale(scale);
  final float offset = sprite.getHeight() / Level.TILE_SIZE - sprite.getHeight() * scale;
  body.setActive(false);
  final float cx = body.getPosition().x;
  final float tx = 0.5f + (int) cx;
  final float deltaX = tx - cx;
  body.setTransform(cx + deltaX / 2.0f, body.getPosition().y, 0);
  sprite.setY(sprite.getY() - offset / 2);
}
See? It makes no sense, I wrote it and I have to really think about it to figure out what it does. That's not good.
Upside is that as long as I make visual progress I don't lose interest in the project.

Maybe you could just try to programmatically animate the door's horizontal scale from 1 to 0.1 or something while darkening it a bit. That might be enough to make it look like it's swinging open.
Possibly. The problem is that the door is just tiles in the tilemap and I don't think I can animate tiles that way (as in transforming them). But it's a good point and I'll investigate it.
Logged

Current devlog; Grapple
Try Hovercraft for Android, voted "a game" by players.Hovercraft on Google play
oahda
Level 10
*****



View Profile
« Reply #9 on: December 16, 2014, 04:50:50 AM »

Oh, wow. I try to make sure that every fourth session or so of mine is refactor session.
Logged

bornander
Level 1
*



View Profile WWW
« Reply #10 on: December 16, 2014, 12:51:16 PM »

Ïnflicting damage is implemented, it's now possible to take damage from falling, fire, and spinning saw-blades.
Falling:

Burning:

Saw-blade:


Initially I screwed up the blood generation and it yielded a beautiful fail  Facepalm.
Logged

Current devlog; Grapple
Try Hovercraft for Android, voted "a game" by players.Hovercraft on Google play
bornander
Level 1
*



View Profile WWW
« Reply #11 on: December 19, 2014, 02:54:42 PM »

So this is moving along at a steady pace and I think I have the core game-mechanics implemented.

I made a short game-play video showing off most, but not all, of the features:


Biggest tasks left in terms of programming are;
  • Main menu screen
  • Settings screen
  • Google leaderboard/achievement integration
  • Clean-up (it's getting a bit out of hand in some places Concerned)

The game is supposed to have 32 levels, so right now the hard work will be creating the levels. Since the player starts out without the grappling-hook I want the levels to be such that it's worth revisiting them with the hook as short-cuts may have become possible, thus allowing the player to score a better time.

Logged

Current devlog; Grapple
Try Hovercraft for Android, voted "a game" by players.Hovercraft on Google play
oahda
Level 10
*****



View Profile
« Reply #12 on: December 20, 2014, 06:16:43 AM »

Oh, is it kinda like SM64 with a main hub leading to all of the levels, or like Fez, with a hub leading to levels leading to levels leading to levels?
Logged

bornander
Level 1
*



View Profile WWW
« Reply #13 on: December 21, 2014, 06:04:04 AM »

Oh, is it kinda like SM64 with a main hub leading to all of the levels, or like Fez, with a hub leading to levels leading to levels leading to levels?

It's a central hub for all levels, there's no nesting of levels. If I had more time I would like to have it Fez-like, but I think that is better suited for games where the exploration is part of the game-play.

I want the user to be able to pick the order he/she plays them, but at the same time I want to be able to limit that choice to a certain degree. I'll try to do it by making certain parts of the central hub in-accessible if certain levels or objectives haven't yet been completed. But I am not sure how to do that right now, so it might not pan out.
Logged

Current devlog; Grapple
Try Hovercraft for Android, voted "a game" by players.Hovercraft on Google play
EdFarage
Level 2
**


I can upload avatars


View Profile
« Reply #14 on: December 21, 2014, 03:43:28 PM »

that gory death doesn't really fit into the game  Who, Me?
Logged
bornander
Level 1
*



View Profile WWW
« Reply #15 on: December 21, 2014, 11:22:29 PM »

that gory death doesn't really fit into the game  Who, Me?
That's a fair point, it does clash a bit with the pixely/cartoony look. I was hoping the ridiculous blood-spray would add a bit of dark comedy to it, but it might not work as well as I intended. I appreciate the feedback, thanks for taking the time to comment.
Logged

Current devlog; Grapple
Try Hovercraft for Android, voted "a game" by players.Hovercraft on Google play
bornander
Level 1
*



View Profile WWW
« Reply #16 on: December 25, 2014, 11:40:02 AM »

Some notes on the onscreen-controls I use for this game.
There are four different buttons/commands that the user can invoke
. Left (run/swing left)
. Right (run/swing right)
. Up (jump, climb or open chests)
. Fire (ejects the grappling hook, or detaches the grappling hook if already attached)

Initially I had the user firing the grappling-hook by touching the screen, a line would be projected from the avatar to that position and the grappling-hook would fire along that line. This approach worked fairly well on phones, where I could easily reach all part of the screen without changing my grip, but on tablets and large screen phones it became an issue.

I've tried to solve this by having the arch-buttons (see image below) for firing the grappling-hook. These buttons detect not only presses, but also where on the button the user pressed. This allows me to pick a direction when a press is detected. The left hand side arch fires the grappling-hook in a direction between 12 and 3 o'clock, and the right hand side fires in the range of 9 to 12 o'clock. I'm hoping it's not going to be too confusing for the user to press the left hand side to fire right, and vice versa.



Code-wise, to detect this I simply create a ClickListener that records the touch point, creates a direction based on some origin and notifies the game that the grappling hook has been fired in that direction.
Somewhat simplified it looks like this;

Code:
leftFire.addListener(new ClickListener(){
   private final Vector2 direction = new Vector2();
   @Override
   public boolean touchDown(final InputEvent event, (final float x, (final float y, (final int pointer, (final int button) {
     direction.set(x, y);
     level.fireGrapplingHook(direction);
     return super.touchDown(event, x, y, pointer, button);
});


An additional complication caused by this is that if I'm running right and I want to fire left I would have to use the same thumb, thus slowing down when moving my thumb from run-right to fire-left. I've "fixed" this by having duplicate controls on each side of the screen. That means you can play the basic movement commands in three ways

1. Move left/right with left thumb, jump with right thumb
2. Move left/right with right thumbb, jump with left thumb
3. Move left with left thumb, move right with right thumb and jump with which ever thumb isn't currently "in use".

(it's also possible to do the inverse of point 3, but that's just silly).

I fear these controls might be overly complicated and will frustrate players, but I have no way of determining this until I get someone to do some playtesting for me. They should be agnostic to the player being left or right-handed, though.
Logged

Current devlog; Grapple
Try Hovercraft for Android, voted "a game" by players.Hovercraft on Google play
oahda
Level 10
*****



View Profile
« Reply #17 on: December 28, 2014, 03:55:52 AM »

I spontaneously feel like you should flip them. Touching the right side of the screen to launch the hook left seems weird.
Logged

bornander
Level 1
*



View Profile WWW
« Reply #18 on: December 28, 2014, 02:42:38 PM »

I spontaneously feel like you should flip them. Touching the right side of the screen to launch the hook left seems weird.
I tried that but then direction felt awkward instead. I am going to let this one be decided by the poor sods that get to do the alpha testing.
Or possibly making it configurable.

Actually, most likely that; I'll make it configurable, allowing the user to choose from two different kinds of awkward controls (which is a step up from my last game that only featured one set of awkward controls). 
Logged

Current devlog; Grapple
Try Hovercraft for Android, voted "a game" by players.Hovercraft on Google play
bornander
Level 1
*



View Profile WWW
« Reply #19 on: December 29, 2014, 12:15:21 PM »

I've been playing around with the way a user pauses the game and returns to the main menu, and I've decided to take a minimalistic approach to this.
A small pause symbol in the upper right corner will pause the game and slide in controls for quitting or resuming.
Currently it looks like this (ignore the single-button main menu for now);


In my previous game I had a big opaque dialog box slide in that obscured the level when the game was paused, I did that so that players wouldn't get a time advantage by pausing and figuring out the best way to beat the level without using up any time. I've decided to part from that strategy in this one as it really doesn't prevent the user from achieving the same effect by playing the level many times anyway.
« Last Edit: December 29, 2014, 02:04:31 PM by bornander » Logged

Current devlog; Grapple
Try Hovercraft for Android, voted "a game" by players.Hovercraft on Google play
Pages: [1] 2 3
Print
Jump to:  

Theme orange-lt created by panic