Coming soon: Day of The Tentacle Remastered

Day of The Tentacle RemasteredOriginally released by LucasArts in 1993, Day of The Tentacle to me and many is one of the greatest adventure games of all time. I played through it at least a dozen times, both the floppy and the full talkie CD version when I got my hands on it. Thanks to Tim Schafer’s Double Fine in collaboration with some of its other original creators, we can soon enjoy the remastered edition.

It features fully redrawn HD graphics and remastered music and audio. Thanks to widescreen monitors and the new optional full-screen interface that gets rid of the verb-bar on the bottom, there will be plenty of new art to be seen around the edges. But don’t worry, if you’re like me and love your pixels, you can switch the graphics and/or UI back to the original.

The sound effects and voices were also resampled. They recovered the tapes of the original recording sessions of all voice actors, so we can enjoy the same performances in much higher quality. iMuse is still controlling the music to give you seamless beat-by-beat transitions, but it’s now using higher quality samples.

To top it off, there is a concept art browser and commentary track with original creators Tim Schafer, Dave Grossman, Larry Ahern, Peter Chan, Peter McConnell and Clint Bajakian. And yes, Maniac Mansion is still fully playable in-game.

Whether you’re a hardcore fan or someone who never heard about it, this release is a must have. Scheduled to release on 22nd March 2016, you can pre-order now on GOG.com with a discount or pick up the PlayStation 4 version if that’s your cup of tea.

Share Button
Posted in Blog Tagged with: , , ,

It’s never late to celebrate

Although 1st January came and went without a post, CodeBin is now officially 3 years old. As my regular readers (if any) know by now, it is time for another recap. Here’s what’s happened in 2015…

Well, not a lot actually. 😉

My projects were fairly dormant during this past year. There were a few exciting new features for Mangler.js, and I’m quite happily using it in my professional projects. There were several additions to NumGuess, but developing the assembly versions to a guideline-compliant state was definitely the one I had the most fun with. On the social side of things, I don’t have any big plans with Twitter and Facebook at this point, but I’m happy to report that they racked up an astonishing 12 followers/likes each, breaking the 2-digit mark.

And finally, here are the usual analytics for no apparent reason:

Visitors

2015 saw an 18% increase in unique visitors to 36,661 with 53,049 page views. Thank you all for reading! Especially the Eclipse developer community. 😉

Most popular posts and pages

Projects

Mangler.js (40.0%)
FakeTileAO (28.9%)
NumGuess (20.9%)
EsoInt (4.7%)

Ostudio

C64 Games (28.8%)
Kill Bill (24.8%)
Ocamel (15.0%)
Oscorch (11.0%)
Otron (8.1%)

Visitor sources

Google search (87.0%)
Direct traffic / unknown (6.8%)
Yandex (0.5%)
StackOverflow (0.4%)
Bing (0.3%)
Yahoo (0.2%)
Other (4.8%)

Browsers

Chrome (61.9%)
Firefox (25.3%)
Safari (4.6%)
Internet Explorer (3.4%)
Opera (2.9%)
Other (1.9%)

Platforms

Desktop (94.9%)
Mobile (4.1%)
Tablet (1.0%)
Share Button
Posted in Blog Tagged with: ,

NumGuess for Haskell, Crystal and Swift

Haskell LogoThree new versions of NumGuess have been released this week:

  • The Haskell version was long outstanding, but it is finally here. It was a tricky language at first look, took some trial and error to get my head around the lack of loops and IO tainting. In the end however, everything fell nicely into place, and the finished code has a nice distribution of pure and IO functions. This release marks my first piece of code in a purely functional language.
  • Crystal is a new programming language with a Ruby-like syntax that gets converted into C, then compiled into machine code. The language is still in alpha development stage, but that shouldn’t stop its NumGuess implementation. It is similar to Java in the sense that everything is an object, although Nil values are handled a bit differently. If you find out how to return a nilable int in the inputNumber() function without compiler errors, please let me know. For the time being, it nicely demonstrates the use of tuples. 😉
  • Finally, Apple’s Swift programming language is about to get open-sourced later this month. Although I can’t see a reason why anyone would pick that language over the more established ones on other platforms, let’s celebrate with a NumGuess implementation. The code was written and tested on Swift 2.0 on a Mac, it’s quite possible that it will break with the open version, we’ll get back to that when it’s out…

If you have a suggestion or find a programming language we missed, please leave it in the comments or contribute to the project on GitHub.

Share Button
Posted in Blog Tagged with: , , ,

Overlap2D 0.1.0 release

Overlap 2D logoOverlap2D is a WYSIWYG UI, scene and level editor by UnderwaterApps, which was released as open source earlier this year. Its goal is to separate the game engine from content creation. Currently, it has a LibGDX runtime.

Main features include:

  • Easy import of images, including 9-patch image support and automatic sprite animations from numbered frames.
  • Drag and drop creation of game UI and scenes.
  • Add custom variables to objects for use by your game logic at runtime.
  • Create item groups and layers for easy manipulation.
  • Supports LibGDX particle effects.
  • 2D physics support by creating polygonal hulls for your sprites and composites.
  • Supports box 2D omni and directional lights with optional physics hit checking.
  • Importing complex animated sprites from BrashMonkey’s Spriter and Esoteric Software’s Spine.
  • Multi-resolution support with automatic resizing of assets. You can also customise your game’s UI based on different aspect ratios.

Have a look at this (slightly outdated) instruction video below to see how it works:

Despite the open source release, it was mostly closed for contributions for the past few months due to major refactoring and architecture changes outside the official repo. With the 0.1.0 release, the project is officially welcoming all contributors to help and improve the project. If you think you can help, head over to this blog post to see how to contribute.

The official project repo can be found on GitHub:

Documentation seems to be work in progress, but their YouTube channel has some step-by-step guides to get you started:

Share Button
Posted in Blog Tagged with: , , , , ,

Upgrading Eclipse 4.4 Luna to 4.5 Mars

Eclipse Luna logoEclipse 4.5 Mars was recently released at the end of June 2015. Upgrading is easy as usual and I didn’t experience any errors this time around. Although the lack of a new logo was a bit of a disappointment. 😉

There is a new Eclipse installer that you can try, but if you want to go the simple update route, read below for the updated repo URLs.

Upgrading Eclipse

The upgrade process is exactly the same as before: change your software repositories, check for updates and install them. If you’re using other repos, it is a good idea to export the URLs, just in case the repo settings get wiped after the update, which seems to happen often for me. It is recommended to install all updates to Luna before upgrading to Mars.

Read my old post with detailed instructions and screenshots if you’re not sure where to look, just make sure you use the new URLs listed here.

Eclipse 4.5 Mars repositories:

 

After the upgrade you will be prompted to update your workspace metadata to the new version. If you’re worried that something might break, make a backup before upgrading.

If you’re developing for Android, you should have switched to Android Studio by now. As the ADT plugin is no longer maintained, I won’t list the repo URL here anymore.

Share Button
Posted in Blog Tagged with: , ,

There is no cow level

I’m happy to report that there is no cow level in Diablo 3.

Not The Cow Level

Not The Cow Level

Share Button
Posted in Blog Tagged with: , ,

Mangular.js

I recently started having a look at AngularJS to replace HTML + jQuery spaghetti code, and it is pretty neat. I looked at the todo example on the main website and as simple as it may be, I do think Mangler.js can simplify it a bit more, and I’m tempted to coin the term “Mangular.js”.;) Here’s how.

The original Angular.js todo app

This code comes straight from the AngularJS website’s main page, look over there if you need explanation.

<!DOCTYPE html>
<html ng-app="todoApp">
<head>
	<title>AngularJS ToDo</title>
	<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
	<script>
	
angular.module('todoApp', [])
	.controller('TodoController', ['$scope', function($scope) {
		$scope.todos = [
			{ text: 'learn angular', done: true },
			{ text: 'build an angular app', done: false }
		];

		$scope.addTodo = function() {
			$scope.todos.push({ text: $scope.todoText, done: false });
			$scope.todoText = '';
		};

		$scope.remaining = function() {
			var count = 0;
			angular.forEach($scope.todos, function(todo) {
				count += todo.done ? 0 : 1;
			});
			return count;
		};

		$scope.archive = function() {
			var oldTodos = $scope.todos;
			$scope.todos = [];
			angular.forEach(oldTodos, function(todo) {
				if (!todo.done) $scope.todos.push(todo);
			});
		};
	}]);

	</script>
	
	<style>
		.done-true {
			text-decoration: line-through;
			color: grey;
		}
	</style>
</head>
<body>
	<h2>Todo</h2>
	<div ng-controller="TodoController">
		<span>{{remaining()}} of {{todos.length}} remaining</span>
		[ <a href="" ng-click="archive()">archive</a> ]
		<ul class="unstyled">
			<li ng-repeat="todo in todos">
				<input type="checkbox" ng-model="todo.done">
				<span class="done-{{todo.done}}">{{todo.text}}</span>
			</li>
		</ul>
		<form ng-submit="addTodo()">
			<input type="text" ng-model="todoText" size="30" placeholder="add new todo here">
			<input class="btn-primary" type="submit" value="add">
		</form>
	</div>
</body>
</html>

Simplification using Mangler.js

.todo

Instead of having a simple array to store the todo items, wrap it in a managed Mangler object:

$scope.todos = Mangler([
	{ text: 'learn mangular', done: true },
	{ text: 'build a mangular app', done: false }
]);

HTML and Angular templates

In line with the above changes, you have to change all references to the todo array to todo.items. This affects the {{todos.length}} template tag and the ng-repeat="todo in todos" directive.

.addTodo()

Nothing has to change here, as the todo Mangler object supports the .push() method, just like an array.

.remaining()

Instead of a manual loop, simply use the .find() method to return a sub-set of your items:

$scope.remaining = function() {
	return $scope.todos.find({ done: false }).length;
};

The .find() method returns an array of all items matching the filter, returning the .length property simply counts them in a single line.

.archive()

Using the same condition as above, the Mangler object’s .filter() method removes non-matching items from the .items array:

$scope.archive = function() {
	$scope.todos.filter({ done: false });
};

The shorter Mangular.js todo app

Mangler.js can greatly simplify working with JavaScript objects and arrays, you no longer have to write multiple lines of code for simple operations. Here’s the shortened code:
Read more ›

Share Button
Posted in Blog Tagged with: , ,

Mangler.js javascript aggregators

Mangler.js‘ new .aggregate() function helps you do calculations on sets of values with the least amount of coding.

Syntax

As usual, it comes in two flavours: as a static utility function or as a Mangler object method:

Mangler.aggregate(collection, aggregator, options);
Mangler(array).aggregate(aggregator, options);

Parameters:

  • collection: Any array or iterable object to get the values from.
  • aggregator: String identifier of the built-in aggregator function to use. You can also pass your own aggregator function.
  • options: An object with optional parameters. If a string is passed, it is handled as the value option.

Options:

  • value: Rather than using the values in the collection directly, use Mangler.getpath() to get its sub-item.
  • group: Path of the field to use as a group identifier to process the data in batches. Can also be a custom function that returns the group name.

Simple examples

var numbers = [6, 10, 20];
var object = { one: 1, two: 2, three: 3 };

// Calculate the sum of an array of numbers
Mangler(numbers).aggregate('+');  // returns 36

// Calculate the sum of object property values
Mangler.aggregate(object, '+');  // returns 6

var products = [
	{ name: 'cherry', type: 'fruit', price: 3.00 },
	{ name: 'orange', type: 'fruit', price: 2.90 },
	{ name: 'grapes', type: 'fruit', price: 1.00 },
	{ name: 'carrot', type: 'vegetable', price: 2.00 },
	{ name: 'celery', type: 'vegetable', price: 3.50 }
];

// Calculate the average product price
Mangler(products).aggregate('avg', 'price');  // returns 2.48

// Collect all product names into an array
Mangler(products).aggregate('[]', 'name');
// returns ['cherry', 'orange', 'grapes', 'carrot', 'celery']

Built-in aggregators

  • "sum": The sum of all values. Aliases: "+", "add"
  • "mul": Multiply all values together. Alias: "*"
  • "avg": The average of all values.
  • "cnt": The number of values found. Alias: "count"
  • "min": The smallest value. Alias: "<"
  • "max": The largest value. Alias: ">"
  • "array": Returns an array of all values. Alias: "[]"

Grouping

// Count products by type
Mangler(products).aggregate('cnt', { group: 'type' });
// returns object: { fruit: 3, vegetable: 2 }

// Get the lowest prices per product type
Mangler(products).aggregate('min', { value: 'price', group: 'type' });
// returns object: { fruit: 1.00, vegetable: 2.00 }

A custom grouping function takes two parameters (key, item) and returns a group name or identifier, which will become property names of the returned object. key is the array index or object property name of the item within the collection. The following example collects product names grouped by their first letter:

var getFirstLetter = function(k, i) { return i.name[0]; };
Mangler(products).aggregate('[]', { value: 'name', group: getFirstLetter });

Returns:

{
	c: ['cherry', 'carrot', 'celery'],
	g: ['grapes'],
	o: ['orange']
}

Custom aggregators

You can pass your own function instead of an aggregator name. The aggregator function gets called for each item in the collection and updates the result. The final result has to be calculated on every call, as there may or may not be further items in the collection. It only needs to generate a single result, grouping of items is handled outside of this function.

It takes three parameters:

  • k is the key of the item in the collection, either an array index or an object property.
  • v is the value to be processed. Either the item itself, or a part of it extracted by the value option.
  • a is the aggregator object, its value is preserved between aggregator calls. The value of a.count is the number of values processed so far, including the current one (starts at 1). The result has to be put into a.result. On the first call, a.result is undefined.

This is the built-in sum aggregator as an example:

function(k, v, a) {
	a.result = a.count === 1 ? v : a.result + v;
},

Advanced aggregators

Special getters can be used to simplify aggregators and queries. This example registers a special getter to the Date type to group items automatically:

var days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];

Mangler.registerType(Date, {
	get: function(date, key) {
		if(key === 'dayOfWeek') {
			return days[date.getDay()];
		}
	}
});

var data = [
	{ qty: 1, date: new Date('2015-03-01') },
	{ qty: 4, date: new Date('2015-03-02') },
	{ qty: 3, date: new Date('2015-03-03') },
	{ qty: 7, date: new Date('2015-03-04') },
	{ qty: 4, date: new Date('2015-03-04') },
	{ qty: 9, date: new Date('2015-03-05') },
	{ qty: 2, date: new Date('2015-03-06') },
	{ qty: 1, date: new Date('2015-03-07') },
	{ qty: 3, date: new Date('2015-03-08') },
	{ qty: 2, date: new Date('2015-03-10') },
	{ qty: 1, date: new Date('2015-03-11') },
	{ qty: 4, date: new Date('2015-03-12') },
];

// Get total quantites per day of the week
var result = Mangler(data).aggregate('+', { value: 'qty', group: 'date.dayOfWeek' });

console.log(result);

Result:

{
	Sunday: 4,
	Monday: 4,
	Tuesday: 5,
	Wednesday: 12,
	Thursday: 13,
	Friday: 2,
	Saturday: 1
}
Share Button
Posted in Blog Tagged with: ,

Mangler.js transform, deflate and inflate

It is time for some new features, fixes and breaking changes to my Mangler.js object processing library. As I started using it in my projects myself and it seems pretty stable, it might even see an official release soon.

Transform

Formerly known as .toCase, it transforms strings between snake_case, camelCase and TitleCase. It no longer takes an array of tokens as input, but can transform a whole array of strings, or even the property names of a passed object. Option properties have also been renamed to transform for all functions that supported toCase.

// By default, auto-detects source transform
// These both return "FooBarBaz"
Mangler.transform('foo_bar_baz', 'title');
Mangler.transform('foo_barBaz', 'title');

// You can specify source and target transforms to avoid guess-work
// This example ignores the primary snake_case detection
// Returns "Foo_barBaz"
Mangler.transform('foo_barBaz', { from: 'camel', to: 'title' });

// When processing multiple strings, you can set an ignore list
var o = { one: 1, two: 2, three: 3 };
Mangler.transform(o, { to: 'upper_', ignore: ['two'] });
// returns o, which is now: { ONE: 1, two: 2, THREE: 3 }

It supports the following transformations:

  • "_": The default sNake_cAse transformation.
  • "upper_": ALL_UPPERCASE_SNAKE_CASE
  • "lower_": all_lowercase_snake_case
  • "title": CapitalisedTitleCase
  • "camel": usualCamelCase
  • ".": dot.delimited.words

Deflate

Formerly called .flatten(), this functionality is not new. It takes a JavaScript object and completely squashes its nested objects and arrays into a single level.

// Example object:

var o = {
	user: {
		id: 'jsmith',
		name: 'John Smith',
		roles: ['Admin', 'User']
	}
};

When called without options:

Mangler.deflate(o);

Result:

{
	user_id: "jsmith",
	user_name: "John Smith",
	user_roles_0: "Admin",
	user_roles_1: "User"
}

Optionally, it can be limited to only take a certain number of iterations from the root.

Mangler.deflate(o, { limit: 1 });

Result:

{
	user_id: "jsmith",
	user_name: "John Smith",
	user_roles: ["Admin", "User"],
}

By default it generates snake_case property names for deflated items, specify the transform option to use one of the above text transformations.

Mangler.deflate(o, { transform: 'camel' });

Result:

{
	userId: "jsmith",
	userName: "John Smith",
	userRoles0: "Admin",
	userRoles1: "User"
}

Object properties will be deflated in-place, clone the object first if you need the original structure, or reverse it with…

Inflate

Reverses the effect of deflate. When called on the first two results above without options, it restores the original object.

Mangler.inflate(o);

With the limit option, you can limit processing to a certain number of levels, starting from the last word of the property name:

Mangler.inflate(o, { limit: 1 });

Result:

{
	user: {
		id: "jsmith"
		name: "John Smith"
	},
	user_roles: ["Admin", "User"]
}

You can also use the transform option to run the resulting property names through .transform(), and the from option to change how words are detected in property names. Both of these options default to snake_case.

Conclusion

As usual, you can call all the above methods on Mangler() object collections as well to apply them to all items, just leave out the first parameter.

If you have any feature suggestions, please let me know in the comments below.

Share Button
Posted in Blog Tagged with: ,

Android 5.0 silent mode missing

The long awaited Android 5.0 update for my Galaxy S5 has finally arrived in an official update. I wasn’t impressed by the battery-sucking change to put a white background on everything, but hey, I’m adaptable, I can live with that.

However after one (1!) day of use I realised that the silent mode has been removed. The sound icon in the notification area used to cycle between sound/vibrate/mute, now it’s just sound/vibrate. The only way to go silent is to switch to vibrate, then go to sound settings and manually take off the vibration intensity. There has probably been some API changes associated with it as well, as many widgets on the Play Store are broken too.

So my question is: who in their right mind would authorise a change to take out a basic feature that’s been in all my mobile phones since my very first one in 2001? If somehow it got into the RC by accident, how many Google testers does it take to identify this as an issue? Of course there are some toggle widgets that’s been updated to work with Android 5.0, but why would I need to monkey-patch a basic feature like that?

UPDATE: Apparently due to public outrage, Android 5.1 will have silent mode back as before, but as the update goes to manufacturers, then mobile providers, it might take a couple of months for the update to be available on your device.

Thankfully Samsung created an update for the Galaxy S5 5.0 branch, which reverted silent mode changes, along with all the priority contact stuff. While the quick fix is quite welcome, this hybrid Android version might introduce some extra incompatibilities to the already fragmented platform.

Share Button
Posted in Blog Tagged with: , ,