I was wondering how a quick random player might fare so I made a simple one. Paste this into your inspector console (or in chrome type "javascript:" into the URL bar and paste it):
My background seems to be significantly different from most people here - what you've written there is something I'd like to learn about, but have no idea where to start.
I've copied your code, hit "F12" in Firefox, but where do I paste it? Where/how does it run?
How can I learn the basics of this stuff without wading through the mindless tutorials intended for people who have never coded?
For reference, I've written safety-critical real-time embedded systems in assembler and C, and these days I write number-theory and expert systems code in Python.
Where can I start that doesn't patronise me to death?
I'm a non-programmer [I've only made programs in BASIC, Fortran, C, C++, assembler, smalltalk, javascript, BASH, probably a couple I forgot (does Maple count), and most recently python (lol - I mean to say my level is 'interested amateur')] but I found this [1] quite a nice reintroduction to javascript the other day.
It gives a good review of javascript syntax, goes over the intricacies of the loose typing system and variable scope, covers some detail on avoiding memory leaks and some browser specifics (which I think are probably out of date; I didn't review it thoroughly I was playing Minecraft at the time) and gets up to anonymous functions and closures.
Aside: Incidentally if someone would like to explain closures to me I'd appreciate it - I don't really understand them.
Code Academy's [2] javascript looks very basic but Code School [3] seems to have better beginner stuff - I've done their git/jQuery courses before and they were quite well done.
As an old joke (a ha-ha only serious joke) goes, closures are a poor man's object orientation, and object orientation is a poor man's closure. Going on the list of languages you have above I'll take it from the object orientation side of the argument. Object orientation works by binding functions to data; the data is persistent for this instance of the object (in the sense that the data remains available as long as the object does) and can be manipulated by the functions bound to that data. Closures on the other hand bind data to functions; so the function is always callable but the data is bound to this instance of the function. So you can have many instances of a function each with it's own data bound to it. In most languages that support closures functions are considered a "first class" data type; i.e. individual functions (and the data bound to them) can be passed just like variables (sometimes with caveats depending on the implementation). Typically this comes hand in hand with "anonymous" functions; functions that don't have an entry in the symbol table, i.e. they don't have a name in the function / object namespace.
If you truly want to understand how it works then you'd probably want to write a compiler that supports closures; you'd then need to cover issues like how to allocate functions on the heap, the difference between locally allocated (typically on the stack) data bound to functions and globally allocated (typically on the heap) data bound to functions.
The second part to closures is understanding the theory, or the why and the high level functionality that it enables, such as callbacks with state or interactions with the likes of recursive (y-combinator like) functions.
Am I correct in my understanding that with a closure, it is one or more data bound to one function, while with object orientation, one or more functions are bound to one or more data?
A singular closure is 1+ data bound to an entity (function). A singular object is multiple data/functions bound to one entity (object).
In the link above there are examples of either generating multiple closures tied to the same set of data (like tel's example), and also examples of having a singular closure that takes as a first parameter a "method" name and branching based on that. Using either solution you have an OO system using closures as your basis.
Closure is a function that "remembers" all variables that were in scope at the place where that function was created. It can then use these variables (as if they were global variables), even if they are outside of the scope when the function is invoked.
These variables also won't get garbage collected because of that.
This feature is most useful when you create anonymous functions that you pass around.
Example:
function foo() {
var localVariable = 3;
return (function () { // this anonymous function can reference localVariable because it is a closure and remembers outside scope
localVariable++;
alert(localVariable);
})
}
var increase = foo(); //foo returns freshly created anonymous function that we assign to local variable "increase".
//foo also created local variable "localVariable"
//and it went out of scope when foo returned,
//but that variable won't be GC-ed as long we keep reference to "increase",
//because increase has that "localVariable" in scope
increase() // we call that variable - it executes that functions and writes 4
function bar() {
var localVariable = 100; //this is different variable with the same name
increase(); //bar can reference increase because bar is a closure, so it remembers outside scope
}
bar(); // writes 5
increase(); //writes 6
var increase2 = foo(); // this creates another function and another localVariable
increase2(); //writes 4
increase(); //writes 7
It's useful for similar things as objects in OO programming (grouping data with code), but encourages different approach to this.
Closures also make functional code with passing functions bearable - without it you would have to explicitly pass variables from scope to each function, or to depend on dynamic scope, so your functions would use different variables depending where they are called.
> These variables also won't get garbage collected because of that.
I should probably be more precise - only the variables from outside scope that the closure actually uses won't get GCed as long as that closure is referenced. Other variables will.
Closures are one implementation of functions. In a language which also has mutable variables, closures create a special kind of private variable behavior.
You're used to thinking of functions which act on things passed into them via their parameters. For instance:
function apply(f, x) { return f(x); }
My example, apply, is a bit unique in that it only uses things passed in through the parameters. More normally, you might also use names of things available in the scope when you define the function, for instance:
function log(x) { console.log(x); }
In this example, the behavior of add depends not only on the parameter x but also the fact that console.log is defined ambiently.
What a closure refers to is the fact that functions can capture names which are only ever available locally thus hiding a reference inside of them. A simple example might be:
function makeExample() {
var exampleText = "Hello world";
return function printer() {
console.log(exampleText);
}
}
var myPrinter = makeExample();
printer();
// Hello world
In this case, the variable `exampleText` is clearly being captured in the definition of `printer`, but since `exampleText` is only defined in the scope of `makeExample`, we have no way of accessing it. The function stored at `myPrinter` has closed over its own copy of `exampleText` can uses it internally in a way we cannot access.
So finally we can turn to the more interesting examples where we combine this closure/capture property with mutability. The canonical example is the counter:
function makeCounter() {
var count = 0;
return {
get: function get() { return count; },
inc: function inc() { count += 1; },
dec: function dec() { count -= 1; }
}
}
var myCounter = makeCounter();
var get = myCounter.get;
var inc = myCounter.inc;
var dec = myCounter.dec;
assert(get() === 0);
inc();
assert(get() === 1);
dec();
assert(get() === 0);
Here, `makeCounter` returns a struct of functions which have all independently captured a reference to the same hidden variable `count`. While I return them all together in an object, I also destructure that object to stress that there's nothing funny going on—the three functions have to be created together to capture the same `count` variable, but afterward they can be separated far and wide.
Since all three functions reference the same hidden variable state they can manipulate it together. This is the magic of variable capture under mutable state: closures.
---
So what's the point?
Well, we've essentially created a private mutable variable on a home-grown object system. There is no way for someone to access the secret `count` reference except via the get/inc/dec functions which have closed over it. This can be very valuable for data encapsulation.
To skip to the punch, Javascript only has a reasonable module system because of closures. If you're familiar with the IIFE-based modules of Javascript they go a little like this
exports = {};
(function(exports) {
var count = 0;
function inc() { count += 1 };
function dec() { count -= 1 };
// With only this function and not `get` exported we can never
// actually view the value of count. This can be very useful
// for implementation hiding and building a minimal API.
function isEven() { return count % 2 == 0 };
exports = { inc: inc, dec: dec, isEven: isEven };
})(exports)
Here we see that the IIFE creates a private, local scope where names like `count` can be created and closed over by exported functions like `inc`, `dec`, and `isEven`. This public/private API building is the core of module creation and, ultimately, it rests upon the creation of closures.
in the console window of the browser tools in chrome or firefox. https://developer.chrome.com/devtools#console note: javascript always runs in the context of a root object. in the browser, it's the window object. if the webpage has multiple frames, you might have to select the correct frame for the console to execute the js in.
This is pretty great - it scored 16 for me on the first go which is higher than my own first attempt of 14.
This script also highlights my main issue with the game. It feels like the rules are not strict enough for this style of game. The real-time nature of the physics combined with the concurrent actions taken by the user results in quite loose game mechanics.
If it wasn't so late I might get into it but I think this could be dramatically improved by just detecting whether a piece is currently underneath another piece. Assuming you can eliminate those as possible choices for the random select process, you would avoid the issue of iterating through a bunch of pieces that can't even be moved during the late game!
Yeah, that would probably help a lot. It is pretty dumb in its current state. That said, sometimes it can join matching tiles that are next to each other in the bottom of the pile, so that can still be useful.
If this was able to achieve any arbitrary number score or even if it was able to consecutively hit scores beyond what a decent player could get, I would agree. But just because playing random works somewhat doesn't make it bad. I'm sure there are new players who would lose in Go to a computer that only placed pieces randomly in valid positions. But with a little skill, another player (or designed algorithm) should be able to almost always beat such the random algorithm.
Yes, of course, in the sense that it is not the best game possible. But it is much less bad than this game. Look at what a Chess AI does and look at this AI.
I loved Threes, 2048 and this is just as great - thanks!
However, one thing that I dislike about this game(and something that could be changed in the next version or permutation) is that gameplay is TIME based instead of TURN based. It makes the game less about strategy and more about being quick with your mouse. It also makes the game less appealing as a background task and something to stop and come back to; ie something to do while waiting for something to cook or during television commercials.
This is great. But I really wish it wouldn't eat my remaining moves because it doesn't see any moves available. The player can rather spend those moves organizing his pieces. As it is, currently the player must also think ahead whether any move will also make the game think there are no moves left, and immediately drop more pieces on top.
or even potentially the counter goes back up for each mach. A single-match move would mean no change in the counter, while a combo move would drive the counter back upwards
I also enjoy the game very much! The only thing that bothers me is the modal dialog at the end- with only options of get the app or restart. What about an option to simply close the modal? For some reason this bugs me. It might be important if you add a variable (faster speed, etc.) that I want to change before I restart.
YES, I like this much better. In particular I like the pieces dropping in from the top and ruining your hard work. The feel is completely changed from frantic pacing to more of a strategy. Very well done.
Nice. It feels like the linking of pieces starts to early, or is even unnecessary. It takes longer to finish a game without it, but the linking feels unnecessary.
Couldn't agree more. I would also add that it's very unappealing due to the fact that I have to use a mouse/track pad at all, though clearly this was made with touch screens in mind. You add that I have to be quick about it too and I find myself struggling to remain interested.
Yeah I never intended or expected anyone to ever play this with a mouse. But I don't mind!
At some point it got posted on some Russian DoTA league site and generated a bit of (mouse) traffic there for a while - I guess those guys are pretty good with a mouse though.
The timer is the game. It's about making matches quickly, and the game would be far too easy if you got rid of the timer. You'd have to make other changes to the format instead, to make up for the lack of timer. Quarter the number of rows perhaps? but then that leaves you at the mercy of the RNG, and it sucks when you lose a game because the RNG dealt you an impossible game.
This game is really great! I think we have the next 2048 upon us. In my few tries I can't get past 15, which makes me keep wanting to do it one more time.
The increasing difficulty to get to higher numbers with the randomness of high-number drops makes the game exciting and the timer makes it frantic.
I look forward to trying two-player mode. Stealing blocks from the opponent is a great mechanic!
The one suggestion I can make is to give high-number blocks (15+?) something to make them stand out, similar to how 2048 indicated higher numbers. The sound effects throughout the game are great!
Thanks so much, I can't tell you how good it is to hear nice things after spending so many evenings fine-tuning everything.
As to your suggestion, you make a good point. It was very hard to come up with 20 distinct colours (let alone 30, as one of the iOS-only modes requires!) and maybe something extra is required.
Adding my congratulations to the others here, especially with regards to how finely-tuned everything is. The art, sound and concept are all great, and I'm sure my problem with the difficulty is down to my lack of skill :-)
Just in case you hadn't managed to get one for testing, I can confirm the game plays perfectly (and is highly addictive) on a Surface Pro 2 using the touch-screen :-)
I don't think that's fair. It's a fun time waster, similar to 2048. I didn't enjoy 2048 very much, but others loved it and it boomed. This game has the potential to perform very well, too, in my opinion. I'm almost certain it'll go viral in the coming days.
I probably won't play solo that much and I'll probably only play the multiplayer a few times. I'm not too into mobile games or small games. Regardless, I think it's a winner.
I must admit I agonised over that initial wording many times over. In the end I said "drop" because many first time players didn't realise it was gravity-oriented and that was just enough of a hint.
It was somewhat by-design that there are a few "secret" mechanics to be discovered.
See, I actually started thinking in 3 dimensions when I read that comment -- like dragging and dropping files, for instance. I didn't realize that they would block each other until a few levels in.
It would turn into 2048 pretty quickly. Obviously the game mechanics are different, but siding two like numbed together is pretty much Threes and by extension 2048 all over.
A few people have said they are keen to play without a timer. The iOS app does have a "Zen" mode (along with a few other variations) but I'm actually thinking of building a separate game where the modes are all turn-based. The hardest thing is thinking of a good name that both associates it and distinguishes it from this game.
I'd enjoy playing without a timer, but with the stack rising after every N moves that don't make a combination. That would force an economy of movement: how can I not only throw this block out of the way, but combine it with something so that it doesn't cause the stack to rise?
First of all it's a really great game! I spend a couple of hours today and finally reached 20!!! HOORAY!
Regarding the name maybe try TwentyRun for time mode and TwentyCalm/Fun for the Zen mode?
Seconded. I like to play simple games in short intervals of spare time, like when I'm waiting for a bus. 2048 was perfect for this purpose. Play for 30 seconds, get distracted, pick up 6 hours later and play for another minute or two.
I really like these kinds of games where the ideal strategy is exactly the opposite of the seemingly obvious play. In my few tries it appears that the ideal strategy is to ensure that you create the lowest number of unique numbers that you can, rather than racing toward the goal of 20. If you create a few high numbers early, you are courting disaster later in the game because you won't be able to combine them.
1. Love the tutorial, super simple and I loved how you introduced harder concepts like linking blocks later on.
2. The objective is clear and challenging right from the get-go, as opposed to introducing levels, the game just naturally kind of gets harder.
3. After introducing the timer that's when I was like "oh shit just got real" and I felt that pressure made it more fun
You think you've done a bunch of things right here. Nice work.
Fantastic game! It really shines on mobile and you've done a phenomenal job of making sure the block sticks with your finger even with aggressive moves. One usability improvement would be to maintain the "hold" state after a block combines.
So if I'm holding a 3 and bring that to another 3 all while keeping my finger held down and then continue to move my finger somewhere else I don't take the new 4 block with me. I have to raise my thumb and do a new tab and swipe. If I can just keep my thumb down then it makes the game more fluid and you can get some nice chaining/combos going.
Also, if you do put in a leaderboard system then you should definitely involve time, and have the timer running when the game is in "paused" state (not background, but pressing the "pause" button deliberately). I've been "cheating" by pausing to collect my thoughts and plan out my moves.
Seriously, a great game - kudos and hope it's a big success for you.
That moment when you hit 20 and then the "twist" I just got a huge smile on my face :)
Got to 15 on my first try. Would likely have done better with a touchscreen; it's much harder with a mouse. Ultimately, it was the introduction of locked-together blocks underneath other blocks that killed me, and in particular the fact that blocks you already had "loose" can suddenly get locked to other blocks.
The Android version is a ton easier to play, but I feel there is something lost when trying to see the whole field of play on a tiny screen. I'll try it on my Nexus 10 and see if that's any better.
I agree wholeheartedly with the other comments: this is a awesome game and well executed!
Small nit: on Android apps, traditionally pressing the back button when at the "home" or top-most screen of your app will either exit, or prompt to exit.
It was also extremely not obvious how to disable the sound; traditionally I would have expected that to live under the "More ... " item at the home screen.
I hope these are taken merely as suggestions, and not as criticism.
I'd love to try this with the ability to 'throw' tiles around, so they maintain some velocity after letting go of them. Obviously they'd still have to snap to the grid but it would be cool to be able to chuck a tile from one side of the screen to the other.
I was able to get 20 by obsessively combining small tiles first, but just barely. The biggest problem is the rows that calcify and lock together if you don't actively try and break bonds.
The bonds only form with new tiles emerging from the bottom, so it's best to keep the bottom as clear as possible. Also, the timer will skip ahead to a new row if there are no immediate moves left, so it's best to maximize the number of possible moves.
The best strategy I've found is to build two towers on either edge of the board. One tower is reserved for #1-9, and the other side is reserved for 10-19. I aggressively clear the bottom and break any links, and then I optimize the storage of my towers. There's only enough space for stacks 8 high, however, so sometimes I need to make a third stack in the middle (ideally with 9, 10, and 11). I've gotten as high as 20x8 on iOS this way, but it takes some luck.
Interesting! I converged to (almost) the same strategy (I just frantically keep #1-9 at one end (1 column with overshoot to a seconds or third), and #10-19 at the other and try breaking bonds asap). It got me to my first 20.
It's c++ with SDL and as little platform-specific code as I can get away with. eg. low latency audio on Android was impossible using stock SDL.
The web version was originally a straight recompile with emscripten but it was way too slow so it's a hybrid approach where the board engine is emscripten and the UI is rewritten with HTML/canvas.
Not at all! This is a mobile game and getting 60 FPS on mobile in a browser is not trivial, even with graphics as simple as these. But natively? Ridiculously easy.
Looking forward seeing the app climb -- I wonder how high this will climb on category ranks? Right now it looks like you've gotten a couple of thousand of downloads on iOS (spike in russia), a couple of hundred on Android. It will be exciting to see the app explode!
Suggestion: Mark tiles at the bottom of the screen as being "attached" to other tiles before said other tiles come onto the screen.
It's very annoying when I see a useful tile which is not attached to anything and I reach over to grab it, only to have it become attached to something in the mean time. (Especially if that tile was one I created by merging two other tiles together and so its attachment to anything else should have been broken.)
good game! hope you get valuable feedback and make a mint.
17. because of later pieces joining together in 3's, it seems it might be impossible to reach 20? (do you ensure there's a soln?)
(android version) i found the touch becoming unresponsive on the edges, in later stages. pr because i'm getting frantic, and using a crappy phone. but if this could be improved (eg larger hit area on the edges - or zoom to cover whole screen), it would be worth it.
apart from the feeling of frustration, the gameplay problem is you lose much time repeating the movement x2 or x3 times, which is crucial to avoid locking joined pieces and large surface area towards the end.
PS would be better if it didn't require any permissions at al. it just seems to be storing twenty.jpg - necessary.
also "throwing" blocks with momentum as another comment said would be cool, and wouldn't undermine gameplay.
I understand how people can find this fun, but not how they can find it "just as good" as Threes!. The graphics are a blatant ripoff, albeit of a lower quality, and the game mechanic is simply way less inventive.
Threes! had attention to detail — in the mechanics, in the visuals, and especially in the music. These ripoffs have none of that.
I can't help but wonder whether we are promoting the tradition of cheap, carelessly made mobile games as opposed to the finely-crafted products. This is why many developers have started to steer clear of the mobile market.
(I don't mean to ruin everyone's fun, just commenting on the larger scheme of things)
That was great until I discovered I was allowed to drag things out from under other things. IMHO the game is a lot more fun if you're under that constraint! Maybe call it "hard mode"...
Great work! This game is good as it is, but you could try having cars/space-ships/gems or whatever instead of numbers, to give you more freedom for experimenting and maybe change the order so that there will be more fall-though. People totally love when much happens with little input.
If the game where to improve, I would say you need to increase the output vs input, making more stuff happen, faster and easier.
thought it was gonna be easy, then noticed the timer on the top when the screen was about halfway full, definitely added another layer of excitement to the game
edit: 18 on 2nd try... can't stop playing! ahem.. is there a way to disable the timer?
Just tested it with my laptop. I was thinking "This is one of those games that works best with a touchscreen." Then I saw that it's available for iOS and Android and went to get it. Btw, when you search for "twenty" on Google Play this app is not the first result. Does Google Play have any SEO options to get you higher on the list?
Getting downloads will help me. I'm already pretty easy to find on the iOS appstore (due to the app having more downloads), but having a common word as a name makes the initial release harder.
This is really well designed, smooth and intuitive. A lot of fun. I can see that a lot of attention was given to the details. I'll be addicted for a while...
(the best strategy I found so far is to use move everything into 3 columns (left, centre, right) as soon as new pieces arrive, only then start merging... top score of 18 at the moment)
I finally got to twenty when I switched to a >10 left, <10 right strategy. Could have been coincidence, could have been the strategy. It's time to get some work done so I'm not gonna figure that out :)
For android, change the color of the yellow for number four, five, eight. I cannot see it well. Either make the number fonts darker (contrast the light color with dark colored fonts so it will be more visible) or change the color to something darker like blue, violet or orange. Nice game.
Bug report—maybe? If you have multiple rows of tiles, you can't drag a tile from a lower row to the game area. It bumps into a tile in a higher row and refuses to move. You need to first move the ones in the higher row to move the tile in the lower row.
At a basic level, it was "Money Idol Exchanger" (an old arcade game my girlfriend really wanted on her iPad) meets 2048.
I have no idea where the link mechanic game from. The game needed more constraints on how pieces could be moved, and that idea just popped into my head one day.
I was unable to get it to work in Firefox or Chrome (even tried disabling extensions on both), but it seems to work okay in IE. I was unsure if it was even meant to be played with a mouse at first.
I freaking love this. I'm pretty bad at it. I especially like the fact that I can play the game on the website and then have an iAP to give you some money. So I paid the iAP.
There has already been one, in fact (on Android). Copied my icon, the look and feel, etc. Fortunately the guy was pretty cool about it and removed it once I asked him
Thanks, I'm actually a little bit proud of them because the combination sound effects actually form a little chord progression all the way up to Twenty.
(I haven't read TFA but I gather it has to do with javascript.)
Javascript is wildly popular these days, many make the reasonable claim that it is the world's most-popular programming language. Lots of people say it's so much fun.
I first learned a very modest bit of javascript a few years ago, I learn more when I need it, more recently I got about halfway through O'Reilly's "Learning Javascript" but am now stopped dead because I regard it as so tedious and dull.
Mind you I am not by any means a language zealot. If you enjoy javascript then more power to you.
But I myself would rather chew my own foot off than actually get paid to write javascript code. Unfortunately I am concerned I may not have much choice.
Is there way you can convince me that javascript can actually be fun and interesting to me?
What I regard as fun is sweating over how to reduce cache misses in my iOS conway's game of life implementation, Warp Life. I once write an AES hard drive encryptor that ran entirely onboard the Oxford OXFW911 Firewire/IDE bridge chip. It had a 49 MHz ARM7TDMI CPU, 64 kB of 16-bit flash with a five-cycle read time, and 1800 bytes of 32-bit ram with a one cycle read time.
FireWire Encrypt was a tough project but I had a grand old time working on it.
My gripe with javascript is that it is simply not possible for me to use it to solve the problems that interest me.
The highest I've seen it manage is 17.