PROJECTS
BLOG
YouTube
Twitter
Bomberman is coming together

Development of my bomberman-clone is coming together well. There's quite a bit left to do, but the networking code is solid, and it does work.

Assets

A lot of the art is still placeholder, even if it is the second or third iteration. One of the things I'm interested in is character customization, I made a basic model, and some optional extras; These include different eyes, hair and a skirt. The colours are also switchable, with 32 current palletes. Here are two configurations


More on Tumblr

Bugs

There are a lot of 'bugs', but nothing that seems difficult at this stage. I need to update it to have the same rules as the original bomberman, where you can't walk through bombs, and where explosions can start chain reactions

Touch Controls

I plan to make this work in mobile browsers, which required some research about touch controls. I've blogged about it, but I'm still yet to integrate it into the game. The development and test cycle is much faster on the PC, so I'll focus on it until the game mechanics are all in.

Other Things

I started making a  mind map of things to do, and it's a bit daunting. You can view it here. It's been about 5 weeks of on-and-off development, and I think it's still on track.

Touch Controls in Dart

A few weeks ago I tweeted about making a bomber-man type game, and was asked if it worked on the phone

I looked around for some resources in Dart without much luck, so I took up upon myself to write this, to help future developers devlop for touch screens.

Im this example, the left half of the screen controls the players 'action' (like jumping) and the right half works like a thumbstick on a conventional controller.

If you just want to see the code, without explaination, you can see it here on Bitbucket and try the demo here

Step 1, Detecting the touch events on a canvas

Here in out main method, we find the canvas element (with the id "canvas") using querySelector(). Using that element, we listen for a bunch of touch events. In this case, touchEnd, touchCancel and touchLeave are treated as the same.

The controls object is where we will implement the handling of these events.


CanvasElement canvas;

void main() {
  canvas = querySelector("#canvas");

  canvas.onTouchStart.listen(controls.start);
  canvas.onTouchEnd.listen(controls.end);
  canvas.onTouchCancel.listen(controls.end);
  canvas.onTouchLeave.listen(controls.end);
  canvas.onTouchMove.listen(controls.move);
}

Step 2, Touch Start

The start method takes the first touch from the changedTouches list and calculates its position (pt) within the canvas.

If the position is in the right half of the canvas: we record the ID of the touch, and set the start and end points of the touch to the current position.

If the position is on the left half of the canvas: _action is set to true.

e.preventDefault() stops the touch from being interpreted as a scrolling motion.


class TouchControls {

  bool _action;
  int _touchId = -1;
  Point _endPoint;
  Point _startPoint;

  start(TouchEvent e) {
    Touch touch = e.changedTouches.first;
    Point pt = touch.client - canvas.getBoundingClientRect().topLeft;
    // Right Half
    if (pt.x >= canvas.width ~/ 2) {
      _touchId = touch.identifier;
      _startPoint = pt;
      _endPoint = pt;
      e.preventDefault();
    } else {
      _action = true;
    }
  }
//...
}

Step 3, Touch End

When the user stops touching the screen, we need to stop moving the character.

e.touches contains a list of all current touches (which doesn't include the touch that just ended in this event). We use the where() method to get a list of all current touches with the id we recorded in _touchId.

If touches no longer contains the touch we are tracking, then we reset the touch id to -1 (assuming this id is always positive). We also reset the _direction that we will be using to record the direction given by the user. The possible values of direction are 0-4, the static constants NONE, LEFT, RIGHT, UP and DOWN


class TouchControls {
  //...
  int _direction = 0; // none, left, right, up, down
  static const int NONE = 0;
  static const int LEFT = 1;
  static const int RIGHT = 2;
  static const int UP = 3;
  static const int DOWN = 4;
  //...

  end(TouchEvent e) {
    List t = e.touches.where((Touch tt) => tt.identifier == _touchId);
    if (t.length == 0) {
      // identified touch isnt it the touches list any more
      _touchId = -1;
      _direction = 0;
    }
    e.preventDefault();
  }
//..
}

Step 4, Touch Move

We are only interested in the touch with the id _touchId (captured in the start() method), so using a where() again, we get a list (of 0 or 1) touches with the given identifier. If it's empty, then this event is ignored.

As in the start() method, we calculate the position on the canvas, and we make sure it is still in the right half. If it is, then we set the _endPoint and make a cal to calculateDirection(), where we calculate the direction of movement based on the start and end points.


class TouchControls {
  //...

  move(TouchEvent event) {
    List t = event.changedTouches.where((tt) => tt.identifier == _touchId);
    if (t.length == 0) {
      return;
    }

    Point pt = t.first.client - canvas.getBoundingClientRect().topLeft;

    // Right half
    if (pt.x >= canvas.width ~/ 2) {
      _endPoint = pt;
      calculateDirection();
      event.preventDefault();
    }
  }

  //...
}

Step 4, Calculate the Direction

Now that we have a start and end point, we can  calculate the direction. We also introduce a "dead-zone", a small circle near the start of the touch that does not have any direction, much like the default position of a thumbstick on a conventional controller.

The variable vec is the difference between the end and start points, and is used to calculate whick quadrant (starting at 45 degrees) the user has dragged.

The constructor for TouchControls has a single parameter where you set the dead zone.


class TouchControls {
  //...
  double _deadZoneRadius;

  TouchControls(this._deadZoneRadius);

  calculateDirection() {
    Point vec = _endPoint - _startPoint;

    if (vec.magnitude < _deadZoneRadius) {
      _direction = NONE;
    } else if (vec.x < -vec.y.abs()) {
      _direction = LEFT;
    } else if (vec.x > vec.y.abs()) {
      _direction = RIGHT;
    } else if (vec.y < 0) {
      _direction = UP;
    } else {
      _direction = DOWN;
    }
  }
//...
}

Step 5, the Getters

Getters are simple in Dart. Most here are one liners, except for get action, which resets the value to false for next time.


class TouchControls {
//...
  get direction => _direction;
  get startPoint => _startPoint;
  get endPoint => _endPoint;
  get action {
    bool tmp = _action;
    _action = false;
    return tmp;
  }
}

Step 6, Using TouchControls

How you use this class is up to you. In my example I render a box on the canvas using the 2D context. If you want, you can use WebGL, or you could even just use html elements, moving around the screen.

For me, I'm using this to control the player in my bomberman-type game, and the action 'button' will place the bomb.

If you want to take it further, you can add buttons in the left half of the screen, or record the direction as an angle, instead of the 4 compass directions

Once again, you can find it all here (along with the rendering code) on Bitbucket. The live demo is here

Boring legal stuff: I'm sharing this under the MIT license, basically do what you want with it :)

Bomberman

I started a small side-project with websockets because I recently purchased a VPS that I can host the server on.

Multiplayer game development is something that I don't have much experience in, part from Chair Simulator which wasn't really real-time anyway.

Explosions, walking, colliding all work now with multiple people. Now I just have to make it into a game, with scores etc. Usually this is where I choke and give up.

I hope to release this soon, even without scoring. The interest in Chair Simulator motivated me to 'finish' it, and if the same thing happens with this project, then I may finish it too.

Seth Ladd's blog is a good resource. His name is all over dart resources. If you interested in Dart, then you should probably follow him on twitter too.

 

I'm still working on the level creation of the space game in the background. Some if it's in game already, but some only exists on paper.

Space Update

New features

  • Stars
  • Improved lighting
  • Sound effects

Stars

To make the stars I simply created a VBO of 300 randomly placed vertecies, and render them as points. The shader I created has only an X and Y offset passed in as uniform variables. The stars wrap around by using only the decimal portion (from 0.0 to 0.9999).

Improved Lighting

In the previous post, lights were only casting circle shapes. In real life, most lights come from the ceiling, and spread out. I've added a few more possible shapes for the lights to emit. The doors emit green lights when unlocked, and orange for locked (red is reserved for more serious things). This helps the player see more clearly when a door is unlocked.

Sound Effects

Adding sound was actually very easy, thanks to this post that I found on Stackoverflow. I'm mostly going to be using wav files, but the ability to dynamically create sounds is very interesting too.

Next up is triggering level transitions, and having more than one script for the whole game... and then maybe bears.

Dynamic lights and Bikes

In this video demo, I've attached lights to each of the 'items' in the level. The final product will have lights that cover more area, that can be in different colours, and that can also move or flash.

The demo also shows a little bit of the editor being used to place items, and the player moving around with gravity switching directions

To do the lighting, we first do a render pass of the level (to a frame buffer) with just the lights. The lights in the demos are just circles/ovals that face out to the edge. I used an additive blend to blend the lights together, which I quickly tested using this handy tool.


Click video to view fullsize

I've started testing it running as Javascript in the browser (instead of Dart in Dartium) and it works really well. I'm sure there are a few optimizations I could make, but its looking good so far. If I'm feeling generous, I might put together a demo level showing off the game's scripting abilities

I also made this woman on a bike, which I also posted on my new Tumblr page

hosted on tumblr

And finally, here's a good set of videos on starting to develop games, called YESDEV0

Super shiny

In my last post about my space game, I noted that it looks pretty flat. I've implemented something similar to this technique on RobotLovesKitty, and now it's super shiny.

The lighting I'm using is based on an image, or 'light map' to which the light will be rendered to. The one used here is crazy just for testing, but it shows the tiles, and the gaps between them.

There is also a normals texture to define the bumps per-pixel. I used the red channel for left-right and green for top-bottom. Here's the normals of a curved surface which I use as a reference

I'll need to think of some way to tone it down, and to turn of the effect completely for computers that can't handle it (probably mobile devices). Having dynamic lights that show the contours of the textures I think is going to help set the mood of the levels throughout the game.

 

Once this is fully sorted out, I'll get onto implementing levels to tell the story. (and I'll finish writing the story)

A bedroom with plenty of Space

I've been working on models for my McSpace remake. Here we have a wardrobe, a bed, and a couch.

The first 'act' will start in this room, so I'll need to space-it-up a bit more.

The lighting is flat too. I'm trying to think of an efficient technique for dynamically lighting the level. I tried a form of ambient occlusion, but the effect blurred the edges more than anything else. I might apply a light map over the whole level

I'm sharing some code

I'ver created a repository in BitBucket to share some common code, just in case others find it useful.

BitBucket.org/MadcoreTom/shared

I'm sorry about the lack of documentation at this time, but BitBucket was all like "oh, i can't save your changes, so I deleted them"

The main thing in there is an exporter script for use with Blender, and some accompanying Dart code to use it in browser games or whatever

Space Levels

After giving up on using Box2D for Dart (the language), and then giving up on porting my Java code to Dart, I've started afresh.

I've learnt a fair bit about Dart, and how I want to program with it. Here's my 3rd attempt, with a level editor (in green space)

I've used the model from my previous post as the character (it still needs cleaning up) which I believe looks much better than my previous attempt.

The idea is to have the walls and floors filled in automatically, instead of needing to create a model for each possible combination. I can see that rendering so many small meshes (2 triangles) is inefficient, so I'll probably have to merge them into one after editing is complete.

 

One of the cool features in Dart is this:

bool get isItemSolid => _solidity ~/ 2 == 1;

It's a cool example of:

  • Arrow functions (one-liners using "=>")
  • Getters (looks like a field, actally invokes a method. Less clutter)
  • Integer division (no unnecessary casting)
  • Private fields (start with "_" always)

Edit

Updated with a quick video showing collisions, walls, and baked animation

Up and running

Recently I've been working on a run animation for my character. After tidying it up a little, and creating a new model (still WIP), i came up with this animation

I haven't seriously looked into skeletal animation/rigging ever since highschool, where i used a demo version of 3Ds max. I've decided to get back into it for game development because it brings so much life to a game.

For my space game, I'll be exporting every 5 frames to its own mesh so i don't get distracted writing another exporter/importer. In the future however I'd like to do a whole lot more skeletal animation.

Recent Posts








Random Posts










Tags

Older>