A look into the past.

dsp2017-1.png

Introduction

I’m going to use whatever I can from the previous project. I’ll list some of the know-how which will be useful in Cubicforest.

cubic.png

The gameplay

I’m now 100% sure if I’ll use the original idea of the rules (You can check them here: http://adam.skobo.pl/?p=697). Anyway I have tested some variants and now I have some knowledge about do’s and dont’s for what the game could be about. Although idea is not complicated, I’ll look for ways to simplify it even more.

Tiled levels

I have ready recipe on creating maps in Tiled. It may seem as something easy: jut put elements on the map, export to the file, load the file. But: You have to decide how to organize the layers, how to name them, how to smuggle other level-data needed (like available player tools). Maybe even Java source code for loading that data (organizing in data structures) will be useful. Old post: http://adam.skobo.pl/?p=537.

Cubic models

And now an absolute time saver. How to build 3d models, export them to the .blend file, convert it to JSON and then make an import to the game. Little Python magic involved, as it’s a native language for the Blender.

blender.jpg Blender models examples. Their 2d representations visible on the previous screenshot.

How to build a 2d sprite is an another interesting topic. Depending on the 2d perspective, cube’s texture should be drawn in the right order to recreate model in the isometric projection.

Old source code

Not sure if the source code itself will be useful: it does not have some complicated algorithms and neither the noteworthy code structure. But it’s good to have a look on the old files. Maybe something interesting will be noticed.

Solver

Ok, one component is definitely worth of attention: levels solver. Previous version has a component which recursively checks all the possible player’s decisions and gather the winning ones. The way to do it, taking into account level’s structure, is not so obvious.

So in the end: I’m glad that the abandoned project will have a second chance. A Javascript one.

written in Emacs with org2blog mode

Why it’s not finished?

dsp2017-1.png

Introduction

As the present contest app is a rewrite of the Cubicforest-java project, I would like to write about my thoughts, why it wasn’t finished. Nonetheless, I’m happy with the results: what I’ve learned is mine. It wasn’t only a software development lesson, because writing a project requires also other skills.

Write small (not)

I think it’s a quite common reason of failure in finishing any vision. Not adjusting the available resources to the project’s requirments. And by that I mean mostly the number of developers, which in case of a home projects is one. That, plus the available time and patience. How long will You endure, writing the same project on and on, after hours and during the limited time on weekends? Will the desire of implementing Your vision be enough?

We’re starting too big, dreaming about creating something original and recognizable. Risking not finishing anything. Not realizing that finishing something smaller will give us enough satisfaction and fun to start something new very soon.

So yes: Cubicforest turned out to be too big to finish before burnout. I would say it’s finished in 60%.

Still learning and always will.

I’ve read somewhere, that rewriting projects could be a good exercise. The best way to learn is to write, write, write. We’re learning new things, getting back to our old source code and rolling our eyes, thinking ‘how could I ever write something like that’. And that’s the thing: the bigger the project, the harder is to perform the desired refactoring. Of course if it’s an extremely important project, we’re agreeing on compromises by doing only some of the needed changes: generally because of the lack of time. Or motivation.

And one more time: that’s why writing smaller hobby projects is better. We can start over without the luggage of bad assumptions. I wasn’t completely dissatisfied with my code. Once I even wanted to continue the project. But right now I’m too tempted to write it better. With the new language I’m learning, new blog posts read, new practice. I want to use experience from that project and mix it with new things I’ve learned lately.

Not doing it fast.

Hm. I thought this post will be longer, but I’m finding only two mentioned reasons.

Too big project.

Want to and will write it better.

I will add another one, pretty similar to the first. Don’t let yourself to work on something too long. You’re losing impetus.

written in Emacs with org2blog mode

Dajsiepoznac2017 contest app.

dsp2017-1.png

New edition of Dajsiepoznac contest has begun. It’s the new era for my blog (hopefully) and I’m going to write here only about concretes. Without story telling or unnecessary ‘blah blah blah’ (am I the only one annoyed by the ‘blah blah blah’ on the blogs?): let me begin.

I’m going to reactivate my unfinished Cubicforest game project (https://github.com/adamskopl/cubicforest-java). Written in Java using LibGDX library. Extremely enlightening experience, lots of work, lots of learning. Why it’s not finished: that’s a topic for the next post.

tiled-cubic.png Early version with sprites.

For the new version I’ve chosen my current main language: Javascript. I’m going to use my experience with the previous version: mainly the way of building and displaying models. The rules of the game are not ready yet, the previous ones seems to be over complicated. For now it does not matter. Despite of the fact, that gameplay details are not known, current basic assumptions will not change:

  • world is built out of one-sized cubes
  • world is isometric
  • gameplay is turn based
  • game world is built from tiles (like on screenshots)
  • characters are moving from tile to tile

cubic.png Late version with all objects built from single cube sprites. Based on 3d models made in Blender

Until I’ll reach that moment, I’ve got a lot of work to do. Mentioned points are my main concern right now. I’ve taken approach to which I’m not fully convinced, but intuitively I’m suspecting that it will not blow in my face. I will concentrate on the display. I will not begin gameplay development until the way of displaying cube-based models will not be ready. Without them my vision has no meaning. Displaying cubes, moving them dynamically, changing their colors, displaying models, destroying them: these are my main concerns.

With cubic engine ready, I’ll try to finish a simple turn based game. 3 month deadline is very cruel. But also very motivating.

Cubicforest gameplay.

written in Emacs with org2blog mode

Collisions trouble.

dp-300x70.png

About lately occurred collision problems.

At first I was satisfied with a first solution for collisions resolving: checking collisions after one movement iteration. What is a movement iteration: a constant time during which objects change their position, normally by moving to the next tile. If an object has a different speed, than it moves at that time a different number of tiles. This ‘movement iteration’ concept gives me more control about game flow: one movement iteration, one positions change for every object.

But lately more situations started coming up. So here are those situations with collisions check implementation explanation.

coll_mov.png

First situation shows a variant which was mistakenly assumed to be the only one. Both objects end their movement on one tile. Both are reported to CollisionHandler:

var GAME_POS = GAME_OBJECT.mov().gamePosTo;
prepareArray(this.tilesToHandle, GAME_POS.x,
        GAME_POS.y);
var ARR = this.tilesToHandle[GAME_POS.x][GAME_POS.y];
(...)
var TILE = this.tilesManager.get(GAME_POS.x, GAME_POS.y);
ARR.push(TILE);

And later every tile is used to make an every to every collision test.

Second situation shows that collisions can occur during movement iteration: when objects are passing each other during normal movement or when one object has bigger speed and passes other object during position change. This forced me to implement something I wanted to avoid: checking collisions on every update(). And this means to get all objects and check every vs every if there are no collisions.

var collObjects = this.gameObjectsManager.getAllWithout(
[GOT.ROAD, GOT.VOID]);
for (var i = 0; i < collObjects.length; i++)
        for (var j = i + 1; j < collObjects.length; j++) {
                this.game.physics.arcade.overlap(
                collObjects[i].sprite,
                collObjects[j].sprite,
                this.onCollision, null, this);

After that, collected colliding pairs have to be merged in collision groups: one group represents objects which are colliding at the exact moment of time in the same spot. So in the end these groups can be passed to CollisionHandler and handled in the same way as collision between objects ending their movement on the same tile.

Third situation: when object is starting movement from the same position as the position of an another object. It’s not a collision, because collision between those objects was already handled. The difference between those objects positions is calculated: if it’s small enough, it means that during collision check, this collision will be ignored.

RunPigsRun: about the progress.

dp-300x70.png

A little report on a progress.

I had some issues with collisions, as it turned out, I haven’t taken into account collisions between objects passing each other. Previously, collisions were only checked, when objects were ending their movement on a tile. It’s a game’s clock: one movement iteration (movement from one tile to another, also with a different speed).

When I have introduced Enemy objects (objects killing Heroes) it turned out, that there is no collision detection between objects passing each other… Collisions where checked when all objects finished their movement on a target tile. I’ve fixed that lately and now collisions events are distinguished on:

  • those fired, whenever collision between objects occur
  • and on those fired, when both objects end their movement on the same tile.

Maybe next time I’ll explain the reason behind this concept.

I have made code easier by introducing ‘void’ type fields, to check collisions for objects which bounces off outside the road. In this way empty fields are also participating in collision tests.

The next thing is choosing tools by a player. The set of available tools is limited and separate for every level (a different set for each level). When player exceeds the limit, the first chosen tool is erased to make room for a new choice. It allows to change decision with a minimum clicking.

Also tools have different modes: e.g. Signpost tool (which changes Hero’s direction) can be rotated. Player changes tool’s mode by choosing again the same field: tool’s next state is chosen and after choosing all the states, the tool is removed. In this way player by a single operation can either change tool’s mode or remove it. It’s an important concept, as more tools will have their modes too.

Clear conditions about lose/win introduced. Now whenever Hero dies (falls into the water/is killed by the enemy/bounces outside the road) the game is lost: black rectangle displayed and level is restarted. Player wins when all the heroes finish their movement on the Exit fields.

Thoughts flow. Inner monologue.

Introduction

This post is related to Dajsiepoznac16 contest in the same way as every IT project/design process/task I was participating in. Whenever any process, which requires planning, is started, I open a text editor and start taking notes. I need this to organize thoughts, ideas, plans, concepts.

Storing ideas

For every project I have a separate file, where everything which comes to mind can be stored. I don’t believe in storing ideas in a head: memory can’t be trusted in this one. Besides: notes can be organized, tagged… and reviewed without a doubt, that something is missing. Notepad is a trusted place. Write down and forget. Your thoughts will remain here.

Head is not the best place to store ideas.

What has to be done?

If I start e.g. a new feature, I’m trying to answer a “what has to be done right now?” question. Every problem, no matter how big, can be divided into concrete steps. In this way, I’m not working on a project: I’m working on a concrete problem, which has clear ‘it’s done’ definition. And one more time: defining these clear steps, can be achieved, by writing down whatever related to solved problem comes to mind. By having the flow of thoughts about the project, the concrete steps emerge spontaneously.

The worst thing is to not know, what has to be done right NOW.

Written down…

It’s said, that to increase a probability of achieving something, it has to be written down. The same goes with planning: thoughts written down are concrete, can be reviewed, modified, updated, commented… they’re becoming more real. It’s almost like planning in a head has no advantage over taking notes. What more, freedom of letting thoughts flow, unblocks other thoughts. The process of one idea chasing the other idea can be sometimes surprising.

Writing things down, can be sometimes an only way to come up with some ideas.

Software

Writing things down with pen and paper has this obvious downside, that it’s incredibly slow. It can be said, almost without a doubt, that taking notes on a keyboard, will be always more effective, as the speed of typing is almost as fast as the speed of thoughts.

org.jpg

I’m using Emacs with OrgMode, which allows to take notes arranged in nested headlines in a surprisingly easy and fast way. It can be seen, that notes are organized in headlines (every ellipsis means, that headline can be unfolded to reveal either more headlines or conrete notes). I think that any software, which allows to write and organize notes fast, will do the trick.

Finding Your ideas is important.

It’s all about the freedom of recording whatever comes to mind.

RunPigsRun: handling collisions.

dp-300x70.png

Collisions in RunPigsRun

One of the things that gives me some confidence about finishing this project is the form of its gameplay. Objects are moved from field to field in a predictable way. Collisions are checked after all the objects finish their movement, which simplifies the work.

Which collisions are already handled?

  1. Hero + Bouncer
    • changes object’s speed
    • plays scaling animation for the bouncer
  2. Hero + Void field; Hero + Water field
    • removes hero from the game
    • reports game’s loss
    • plays field’s scale animation
  3. Hero + Exit
    • removes hero from the game
    • reports that hero was saved

How it’s implemented

I really like Javascript’s duck typing. Earlier Mr. Czocher reported in comments, that I should checkout Typescript, which (I assume from the introduction videos) will make code more standardized e.g. by interfaces. I’m really curious if it will not lower the speed of coding, as with my current code organization I’m having a really small amount of bugs and generally work goes smooth. That was just a small digression. What I want to say, that with Javascript’s conventions I’ve come up with a nice way to define functions handling collisions between pair of objects.

First: objects which ends their movement outside of the map are removed. Before that, CollisionsHandler sends signal about object which is about to be removed and GameResultResolver checks if it’s not a Hero.

/**
 * Every remove should go through here to ensure signal dispatch.
 */
CollisionsHandler.prototype.handleRemove = 
function(GAME_OBJECT, SIGNAL) {
  // dispatch signal BEFORE removing object
  this.signals[SIGNAL].dispatch(GAME_OBJECT);
  this.gameObjectsManager.remove(GAME_OBJECT);
};

GameResultResolver.prototype.slotObjectRemoved = 
function(OBJECT) {
  if (OBJECT.type === GOT.HERO)
    this.resultObject.loss = true;
};

Next all the objects on the tile are compared between each other with handleCollisionPair().

CollisionsHandler.prototype.handleTileCollisions = 
function(TILE) {
  for (var I = 0; I < TILE.length; I++)
    for (var J = I + 1; J < TILE.length; J++) {
      // unique pair (no two objects compared more than once)
      RESULTS = handleCollisionPair(TILE[I], TILE[J]);
      if (RESULTS === undefined) {
        console.error("RESULTS === undefined");
        continue;
      }
      for (var R in RESULTS)
        this.handleCollisionResult(RESULTS[R]);
    }
};

handleCollisionPair()

Now the heart of this post. I was wondering how to write simple code, which will:

  • handle collision result between a pair of objects
  • take into account that the order of passed objects is not predictable (is it HERO vs BOUNCER or BOUNCER vs HERO?)

The solution is quite elegant in my opinion: objects’ type names are used to locate the name of the function returning collision result.

/**
 * Get collision function name by concating object type names 
 * sorted alphabetically.
 */
function getCollisionFunctionName(OBJ_A, OBJ_B) {
  return "collision" + ((OBJ_A.type < OBJ_B.type) ?
    OBJ_A.type + OBJ_B.type :
    OBJ_B.type + OBJ_A.type);
};

So: collision between ‘hero’ and ‘t_bouncer’ gives the same function name as collision between ‘t_bouncer’ and ‘hero’. In this case: collisionherot_bouncer(). handleCollisionPair() returns the result of such function and passed arguments are also sorted alphabetically, which ensures that collision function is invoked always in the same way:

function handleCollisionPair(OBJ_A, OBJ_B) {
  var fname = getCollisionFunctionName(OBJ_A, OBJ_B);
  if (typeof window[fname] !== 'function')
    console.error("no colision function: " + fname);
  if (OBJ_A.type < OBJ_B.type)
    return window[fname](OBJ_A, OBJ_B);
  else
    return window[fname](OBJ_B, OBJ_A); // switch objects (alphabetical order)
};

Collision results

Functions checking collision result return an array of CollisionResult objects which keep data about objects modified as a result of the collision, type of operation which should be performed and optional arguments.

function CollisionResult(OBJECT, OPERATION, ARG) {
  this.object = OBJECT;
  this.operation = OPERATION;
  this.arg = ARG;
};

COLLISION_OPERATION = Object.freeze({
  REMOVE: "remove",
  RESCUE: "rescue", // rescue object (hero)
  SCALE_ANIMATION: "scaleAnim", // temporary firework
  SPEED_CHANGE: "speed"
});

Example of function resolving collision between HERO and BOUNCER:

function collisionherot_bouncer(HERO, TOOL_BOUNCER) {
  return [
    new CollisionResult(
      HERO, COLLISION_OPERATION.SPEED_CHANGE, 2),
    new CollisionResult(
      TOOL_BOUNCER, COLLISION_OPERATION.SCALE_ANIMATION, 1.5)
  ];
};

Easy and clear: collision changes Hero’s speed (bounce) and plays scale animation for bouncer. Now every object from the array is passed to handleCollisionResult().

CollisionsHandler.prototype.handleCollisionResult = 
function(RESULT) {
  switch (RESULT.operation) {
    case COLLISION_OPERATION.REMOVE:
      this.handleRemove(RESULT.object, "objectRemoved");
    case COLLISION_OPERATION.SPEED_CHANGE:
      RESULT.object.setSpeed(RESULT.arg);
      break;
    case COLLISION_OPERATION.SCALE_ANIMATION:
      RESULT.object.startScaleAnimation(this.game, RESULT.arg);
      break;
    case COLLISION_OPERATION.RESCUE:
      if (RESULT.object.type === GOT.HERO)
        this.handleRemove(RESULT.object, "objectRescued");
      break;
    default:
      console.error("not implemented: " + RESULT.operation);
  }
};

In the end.

If the new object is introduced, e.g ‘superObject’, and collision between this object and ‘hero’ object should be handled, only the…

function collisionherosuperobject(HERO, SUPEROBJECT) {
  return [];
};

returning the array of collision results, should be added.

New collision = new function. Easy.

Tiled Editor: composing levels.

dp-300x70.png

What is it?

Phaser framework supports loading data about the maps from a couple of formats. As RunPigsRun is not a complicated game with levels built from tiles, Tiled map editor is a sufficient choice.

How does it work?

First an image presenting a tileset is needed, I’ve got mine from here: http://opengameart.org/content/tiny-16-basic (by: http://opengameart.org/users/sharm). As I’ve mentioned earlier: don’t care how the set looks (although it’s nice). After importing image to program, three types of layers from which level can be built are available:

  1. Background Layer. Tiles on this layer are intended to be used as a background: in the game they will be only displayed. Even putting them in editor reminds drawing with a brush.
  2. Object Layer. Used to create concrete objects represented by a tile image. Such objects can be translated/rotated. They are named and put into an objects tree. In contrary to Background Layer, created objects are exported with information like: position, id of a tile in a tileset or custom properties (properties set by us).
  3. Image Layer. Don’t know, never used it. Probably used to insert an image.

tiled.jpg

After level is finished, it can be exported to many formats. Some of them are easily parsed by Phaser.

Parsing.

First: loading background. Few lines and we’re good to go:

// loading map:
this.map = this.game.add.tilemap(
        'level' + this.levelId); 
// loading image for background:
this.map.addTilesetImage(
        'basictiles', assetsConstants.SPREADSHEET_BASIC); 
this.tilemapLayers.push(this.map.createLayer('background0',
        scaleConstants.GAME_W, scaleConstants.GAME_H, 
        this.groupLevels));

After that, the image has to be scaled and translated. For these I’m using constants:

  • this.tilemapLayers[i].scale.x = scaleConstants.MAIN_SCALE (scale for every visually measurable number in a game, like distances or object’s dimensions)
  • this.tilemapLayers[i].x = scaleConstants.GAME_OFFSET_X * scaleConstants.TILE_SIZE_SCALED (position = map offset in tiles * scaled tile dimensions)

Next: loading objects (like roads or an exit).

var objectsLevel = this.map.objects.objectsLevel;
for (var i = 0; i < objectsLevel.length; i++)
        this.gameObjectsManager.create(
                tileObjectToGameObjectParams(
                objectsLevel[i]));

Written function tileObjectToGameObjectParams converts loaded Tiled object to my GameObjectParams used to describe object created by a GameObjectsManager.

Custom Properties

Right now one object in a game needs an extra attentions: a hut. It has a capacity parameter, which describes how many heroes it will create. Tiled allows to add such ‘Custom Property’ to an object, and later that property if of course shipped along with the other data.

GameObjectsManagerHuts.prototype.countHeroes = function() {
        var cnt = 0;
        for (var i in this.objects)
                cnt += parseInt(
                this.objects[i].properties.capacity);
        return cnt;
};

In the end

Tiled is a concrete piece of software: does its job very well. An easy and a pleasant way to compose a level with a background and objects.

written in Emacs with org2blog mode