[Game]Pine-2K - A Fantasy Console For Pokitto

Based on excellent work by @HomineLudens and @Vampirics, Pine-2K is a Fantasy Console for the Pokitto meant for quick games.

If you only want to play Pine-2K games, then here’s the download for you:

pine-2k.zip (185.6 KB)

Extract the zip into your SD Card (you should have the pine-2k folder in the root of the card) and you’re set.

Changelog

  • v1.4.0 Fix crashes, new code viewer.
  • v1.3.0 Lots of bug fixes, compiler generates smaller code, new built-in functions, new example
  • v1.1.0 Updated with a request from Marketting, minor fixes, new banners
  • v1.0.0 Initial release

If you want to make games, read on!

This is what the full source code to a Pine-2K game looks like.
const minX = 6, maxX = 22;
const minY = 0, maxY = 20;
const boardWidth = maxX - minX;
const boardHeight = maxY - minY;
const heart = builtin("sHeart");
const lvl = builtin("sLvl");
const pts = builtin("sPts");
const ledOFF = builtin("shape2");
const ledON = builtin("sBtn");
const snakeColor = 112;
const bgColor = 113;
const appleColor = 87;
const maxLen = 100;
var snake = new Array(maxLen);
var begin;
var end;
var currentLen;
var len;
var x, y, vx, vy, ax, ay;
var dead, won = 0;
var stepTime;
var delay = 0;
var level = 0;
var inputEnabled = true;
var score = 0;
var prevScore = 0;
var lives = 3;

window(44, 0, 176, 176);
tileshift(2, 0);
io("DURATION", 50);
reset();

function reset(){
    if(lives < 0){
        highscore(score);
        exit();
        return;
    }
    color(bgColor);
    for(y = 0; y < boardHeight; ++y){
        for(x = 0; x < boardWidth; ++x){
            tile(x + minX, y + minY, ledOFF);
        }
    }
    t = 0;
    delay = 100 - (level * 5);
    x = boardWidth / 2;
    y = boardHeight / 2;
    currentLen = 1;
    len = 5;
    vx = 0;
    vy = 0;
    dead = false;
    end = 0;
    begin = end;
    snake[begin] = (x << 16) + y;
    ax = random(0, boardWidth);
    ay = random(0, boardHeight);
    inputEnabled = true;
}

function pattern(x, y, imgName){
    var img = builtin(imgName);
    var w = peek(img++);
    var h = peek(img++);
    x += minX;
    y += minY;
    for(var ty = 0; ty < h; ++ty){
        for(var tx = 0; tx < w; ++tx){
            var c = peek(img, tx);
            if(c){
                color(c - 7);
                tile(x + tx, y + ty, ledOFF);
            }
        }
        img += w;
    }
}

function plot(i, img){
    var c = snake[i];
    var ty = (c << 16) >> 16;
    tile((c >> 16) + minX, ty + minY, img);
}

function hud(){
    color(47);
    sprite(50, 165, lvl);
    cursor(60, 165);
    printNumber(level + 1);
    sprite(110, 165, pts);
    cursor(120, 165);
    printNumber(score);
    color(0);
    for(var i=0; i<lives; ++i)
        sprite(80 + (i * 8), 165, heart);
}

function update(){
    if(pressed("C"))
        exit();

    hud();

    if(inputEnabled){
        if(pressed("LEFT") && (vx != 1)){
            vx = -1;
            vy = 0;
            inputEnabled = false;
        }

        if(pressed("RIGHT") && (vx != -1)){
            vx = 1;
            vy = 0;
            inputEnabled = false;
        }

        if(pressed("UP") && (vy != 1)){
            vx = 0;
            vy = -1;
            inputEnabled = false;
        }

        if(pressed("DOWN") && (vy != -1)){
            vx = 0;
            vy = 1;
            inputEnabled = false;
        }
    }

    if((time() - stepTime) < delay)
        return;
    stepTime = time();
    inputEnabled = true;

    if(won){
        vx = 0;
        vy = 0;
        --won;
        if(!won){
            ++level;
            reset();
            return;
        }
    } else {
        x += vx;
        y += vy;

        if(x < 0) x = boardWidth - 1;
        else if(x >= boardWidth) x = 0;
        if(y < 0) y = boardHeight - 1;
        else if(y >= boardHeight) y = 0;

        if((x == ax) && (y == ay)){
            ++score;
            len += 3;
            if(len >= ((5 + level) * 5)){
                highscore(score);
                prevScore = score;
                delay = 20;
                won = 10;
                pattern(0, 2, "happyEmote");
                return;
            }
            ax = random(0, boardWidth);
            ay = random(0, boardHeight);
        }
    }

    color(bgColor);
    plot(begin, ledOFF);

    if(dead){
        vx = 0;
        vy = 0;
        if(score > prevScore) --score;
        --len;
        if(!len){
            score = prevScore;
            --lives;
            reset();
            return;
        }
        currentLen = len;
        if(++begin == maxLen) begin = 0;
    }

    var growing = !dead;

    if(vx || vy){
        if(++end == maxLen) end = 0;
        snake[end] = (x << 16) + y;
        if(++currentLen > len){
            growing = false;
            if(++begin == maxLen) begin = 0;
            currentLen--;
        }else{
            sound(40, 0);
        }
    }

    color(snakeColor);
    for(var i = begin; i != end;){
        if(growing)
            color(random(0, 255));
        if(snake[i] == snake[end]){
            delay = 20;
            if(!dead){
                dead = true;
                sound(60, 0);
                pattern(4, 7, "sSkull");
            }
        }
        plot(i, ledON);
        if(++i == maxLen) i = 0;
    }
    color(snakeColor-1);
    plot(end, ledON);

    color(appleColor);
    tile(ax + minX, ay + minY, ledON);
}

“Hey, is that jav-”
“No.”

To make PINE games you don’t need an IDE or even a compiler. There’s a compiler built-in already! If you wanted to, you could even use the Pokipad text editor to code directly on the device, getting the full retro computer experience.

However, the process is so much easier using FemtoIDE.

FemtoIDE project for writing Pine-2K games: PINE-SDK.zip (859.9 KB)

Inside the pine folder you will find each project. To make your own, simply create a new folder (with up to 15 characters in the name) and put your code in src.js. Press Ctrl+G to run the emulator (not Ctrl+R) and see your game.


So what is this, exactly?

With Pokitto projects getting bigger and more complex, I decided to experiment with the opposite by imposing an interesting set of constraints. Some of these constraints can be lifted if we decide they’re too harsh. It’s easier to lift constraints later than to do the opposite.

Here are the current constraints:

All logic must fit in 2KB once compiled.

PINE games don’t get “flashed”. When you select a game in the menu it gets compiled directly into RAM1, which is 2KB in size. Since we’re talking about compiled code, it doesn’t really correspond to sourcecode size. Having shorter variable names or putting all the code in one line isn’t going to help.

Just like old consoles, the palette is fixed.

It’s the 256-color Miloslav palette, so it shouldn’t be too harsh of a constraint and it allows you to do lighting effects with recoloring.

Built-in Graphics

PINE comes with a varied set of 16x16 and 8x8 graphics, such as a tileset by Eiyeron & Jerom, from OpenGameArt. Both sizes can be used as tiles or sprites at the same time, together with recoloring. Coupled with the fact that sprites can be mirrored and/or flipped, there is a good amount of freedom. If you need more, you can load graphics from the SD into RAM. The FemtoIDE project comes with a script that can bundle various graphics together into Resource Packs (see Hiragana Flash for an example of it in use). Loading images from a resource pack is fast enough for animation. Finally, you can load 16-bit graphics directly to the LCD (see the sidescreen art in the example games).

Black Box

In the SDK version you’ll find a readme.md and a language.md file that documents much of the API and the language. It doesn’t document every aspect, however. The list of built-ins, for example, hasn’t been published on purpose: discovering and sharing builtins has been left as a bit of a meta minigame: The point is to encourage people to hunt, share and trade easter-eggs.


Why?

Because it’s fun. I had fun making Pine-2K, then I had fun writing (and actually finishing!) each of the included games.
I hope you have fun with it too.

13 Likes

I am so excited to play more with this. I have only been messing around and building/breaking things right now, but it definitely has that Fantasy Console feel! And the bonus of trying to find the hidden features and builtin’s is actually a lot of fun :smiley:

2 Likes

Interesting concept :thinking:

3 Likes

What kind of jam / PINE coding party should we organize?

1 Like

Both zips have been updated with minor new features and a change as requested from the Marketing department.

The frequent kind. :stuck_out_tongue:

5 Likes

Just gave it a quick try on my Pokitto, and the included example games are impressively polished considering how many there are! I like how the flash card games are scored like competitive arcade games.

So is this virtual console actually compiling the code every time it’s loaded? And then is the result loaded as arm machine code into the flash, or is the compiled code virtual machine instructions? I noticed the Pokitto makes a prolonged buzzing sound while it’s loading. Is that caused by loading from the SD card, compiling, or both?

A few minor comments about the games:
I thought it was weird that the snake game resets your length after you get enough apples. Is that a memory limitation issue? Also, the smash game resets the high score after every death, which means that only the high score from the last life is saved.

3 Likes

Yes, it compiles the code every time you pick a game. It is compiled to native arm machine code in RAM, not flash. There is no VM.

Yeah, reading and writing from the SD can produce noise.

It’s not a memory limitation. The higher the level, the more apples there are to collect and the faster you move. It has been many years since I’ve played snake, but I vaguely remember it being like that back then as well.

It also resets the level when you die, so it resets the score to the one you had at the beginning of the level. Otherwise you’d get points for destroying the same bricks more than once.

4 Likes

It looks good. I’d like to make some minigame for it. Though I don’t know what performance I will get with multiple sprites moving around.

I suppose you have included Colored 16x16 Fantasy tileset by Jerom&Eiyeron as built-in gfx:

color_tileset_16x16_Jerom&Eiyeron_CC-BY-SA-3.0_8

So far I have found the following built-in magic codes:

building1, floor1, wall1, door1, tree1, water1, key1, helmet1, scroll1, char1, weapon1, armor1, shield1
fireball, bag, sign, potion, bones, rock, boat, tomb, bed
sShield, sSword, sSkull, sStar

The numbered ones may refer to multiple ones by just increasing index.

6 Likes

The performance should be good as the program is compiled to Asm on-the-fly before executing

3 Likes

Unfortunately, compiling to asm alone does not guarantee performance. It may need some 2K stress testing for the greater glory of science :grin:

5 Likes

If only we knew someone with such experiences and expertise :smirk::wink:

More simplicity, yes please :slight_smile: <3 Made my day.

7 Likes

Really nice mini games and great artwork!

6 Likes

13 posts were merged into an existing topic: [Tool]FemtoIDE

Pine-2k v1.3.0

This update fixes a whole lot of bugs. Many thanks to @carbonacat, @filmote, @SkyBerron, @tuxinator2009 and @Vampirics!

It wasn’t just bug-fixes, though:

  • The compiler now produces smaller code, so fitting your game logic in 2kb might be a little bit easier.
  • Text and Sprites can now be scaled by 2.
  • RTC support. Snake example now shows the time in the HUD.
  • More built-in images.
  • The language now supports operator precedence. Your code doesn’t (have (to (be so) (lispy)) (anymore)).

For more information, see the included markdown files and the examples.

8 Likes

As i didn’t have much time yet (a lot of projects on twitter and youtube and with my daughter i promised), i couldn’t try Pine until today. Couldn’t start it with Kraken Loader and thought it has to be a stand alone application maybe?

Did you remember to put the necessary files on the SD card? Pine needs the sd card

1 Like

Good question, i took the zip and opened it on the sd

Pine-2K v1.4.0

There is no longer an “SDK version” and a “Non-SDK version”. To avoid mix-ups, both bins have been merged into one.
A simple code viewer has been added. Press C+A to view a project’s src.js file. This viewer is also used to display error messages.
Pressing C+B will toggle “Dev Mode”, which takes a bit longer to compile but is much more useful for finding out why a game is crashing.
On the subject of crashing, there should be much less of it.

6 Likes

So, what kind of built-in gfx you all have been able to find in Pine2k :wink: ?

3 Likes