Skip to main content

On Sale: GamesAssetsToolsTabletopComics
Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
TagsGame Engines

hashalon

37
Posts
5
Topics
72
Followers
160
Following
A member registered May 01, 2015 · View creator page →

Creator of

Recent community posts

How does it not replicate the way a game & watch works ?

Bah, il y a des jeux NES qui finissent comme ça... :)

J'ai essayé de faire un sytème à la Mario Galaxy mais il y a encore des soucis à certains endroit.

Les sources sont dispo si vous voulez vous inspirer du projet.

Bon bah... on a fait le même jeu... ;)

I would use godot, so that I can learn the engine.

I can do it in both 3D and 2D, it is almost the same.

super nice pieces !

I can code the game logic of it if you want.

What engine would you like ?

Weird, the itchio app usualy update my version of TIC-80.

But this time it installed the HTML version instead...

the version run directly from the Itchio app has a weird window.

And it is not possible to scale up the screen because all it gives is more white around the screen.

No I mean, it really lacks a mute button. Whatever the game, it should always have a way to disable all sounds so that it can be played while listening to something else.

The game lacks a mute button.

It was inspired by Super Mario 3D World "Cherry" power-up. And the same way that for the dev team, it was a bug that became a feature. I made my characters so that it was easy to implement. I just needed to add a small force so that the clones would push each other to avoid having them on top of one-another.

It is actually possible to have more and longer levels.

And there still room for more enemies, items and environments in the sprite sheet.

So it could become a full game eventually.

Thanks

I would also say that it was exhausting...

thanks, I am still working on it to add sounds effect and clean up the code

TIC-80 community · Created a new topic Operator Overloading
(1 edit)

I just discovered that lua support operator overloading for tables so I had to test it out.

So i tried in TIC-80 and it works, so I though "What about moonscript ?'

It happens that it is that easy:

-- example of the use of lua's metamethods with moonscript's classes
class Vector
  
  new:(x,y)=>
    @x = x
    @y = y
  
  __add:(vecA,vecB)->
    return Vector(vecA.x + vecB.x, vecA.y + vecB.y)


a = Vector 1,2
b = Vector 3,4

c = a + b

print "c.x = "..c.x -- prints 4 (1+3 = 4)
print "c.y = "..c.y -- prints 6 (2+4 = 6)

So it is possible to change the behavior of operators based on the class of the tables.

If other people are interrested, you can read the lua doc regarding metamethods.

LUA's metamethods

Or we could have multiple scripts so that we could split our code into multiple sections.

Maybe a way to add libs to a cartridge could be a way to include it.

Or as a variable in TIC-80: lume.

I think at some point that cartridge configuration will require its own panel rather than few comment lines.

If LUA is hard to learn for you... good luck with C++

LUA is the most simple Language I use for my project. To me it's even simpler than BASIC. And I know how to program in Java, Javascript, Typescript, Python, Moonscript, C, C++, C#.

Just follow a tutorial on LUA, you'll see it is not hard to use ;)

Thanks, I tried your solution and I noticed that there is a bug with the sset function (and surely with the sget function too)

It should be

-- set spriteheet pixel
function sset(x,y,c)
    local addr=0x4000+(x//8+y//8*16)*32 -- get sprite address
    poke4(addr*2+x%8+y%8*8,c) -- set sprite pixel
end

and not

-- set spriteheet pixel
function sset(x,y,c)
    local addr=0x4000+(x//8+y//8*16)*16 -- get sprite address
    poke4(addr*2+x%8+y%8*8,c) -- set sprite pixel
end

I was working on a little projet in TIC-80 and I came accross a problem:

I have a shape made of a circle and a rectangle and I would like to cut pieces of it.So my idea was to draw the shape and simply draw on top of it to remove parts of it. However if I do that, I cannot draw stuff behind of the shape.

So I was wondering if it could be possible to add an optional 'mask' parameter to each paint function:

line    x0 y0 x1 y1 color [mask]
rect    x y w h color [mask]
rectb   x y w h color [mask]
circ    x y radius color [mask]
circb   x y radius color [mask]
tri     x1 y1 x2 y2 x3 y3 color [mask]

So that the function would only draw on pixels of the color specified by the mask. It would be quite useful for demos.

But if it is too much for a machine that is supposed to be limited, I would like to have some hints on how to draw complex shapes. Like maybe there is a way to draw on the spritesheet and then draw back the sprite on the screen.

TIC-80 is based on real LUA on the contrary of PICO-8. And LUA doesn't support shorthands.

If you want to use shorthands like +=, -=, *=, /=, %= you should try moonscript which is supported by TIC-80

I got it !

The counter, as you call it, counts the number of characters in your script regardless if those characters are part of the code or in comments.

This is not a glitch. And do not stop using comments to lower the counter. The counter just display some overall usless information.

https://en.m.wikipedia.org/wiki/Double-precision_f...

If you deal only with integers, your limit is

253=9,007,199,254,740,992

beyond that, you cannot have the direct next natural number:

if I do 253+1 I will get 9,007,199,254,740,994 .

You should definitly use arrays and 'for'-loop, your code is really hard to read.

Use functions to cut your code into multiple simple operations.

Also use comments to explain which part of the code do what.

And beware, TIC implement a more formal LUA than PICO-8. That means that number are double precision floating point number and not 32bit fixed point like in PICO-8. It means that if you increament by a real number, let's say 0.34 every frame and you start from x=0 and you want to check when x==1:

x = 0
while «condition» do
  if x==1 then «do a thing» end
  x = x + 0.34
end
----execution:
x==0
x==0.34
x==0.68
x==1.02 --x==1 is never checked

if you want to use check points with floating point numbers, use intervals instead of discrete values:

x = 0
while «condition» do
  if 0.9<x and x<1.1 then «do a thing» end
  x = x + 0.34
end
----execution:
x==0
x==0.34
x==0.68
x==1.02 --> 0.9<1.02<1.1 --> condition is checked !

You need to get the autorisation from the authors to port games from PICO-8 to TIC

And even though, it is more interresting to make new games specific to TIC rather than ports.

Here I made an update that allow to see the execution of the automaton in real time.

--[moonscript]
--brainfuck interpreter by oSchyns
--version 0.3.0


BF="++++ ++++"..
"[>+++++ +++++<-]"..
">++++.----- ----- -.--- ---."--..
--uncomment to test error output
--"<< force a tape outbound"


IN=""


--tape to perform computation
class Tape
    
    new:(l,m)=>
        @l=l  --cell limit
        @m=m  --loop the finite tape
        @t={} --tape
        @h=0  --read head
        --correct values
        @l-=1 if @l~=nil
        @m-=1 if @m~=nil
    
    --rhead out of the bounds of the tape
    unbound:=>
        if @m~=nil then return @h>@m
        @h<0
    
    --init nil cell to zero
    init:=> @t[@h]=0 if @t[@h]==nil
    
    --move read head to the left
    mvL:=>
        @h-=1
        if @m~=nil then if @h<0
            @h=@m
    
    --move read head to the right
    mvR:=>
        @h+=1
        if @m~=nil then if @h>@m
            @h=0
    
    --decreament cell
    decr:=>
        @init!
        @t[@h]-=1
        if @l~=nil then if @t[@h]<0
            @t[@h]=@l
    
    --increament cell
    incr:=>
        @init!
        @t[@h]+=1
        if @l~=nil then if @t[@h]>@l
            @t[@h]=0
    
    --ins: insert value in cell
    --out: get value from cell
    
    ins:(i)=> @t[@h]=i if i~=nil
    out:   => @t[@h]   or 0


--stack to hold indexes of brackets
class Stack
    new:    => @s={}
    top:    => @s[#@s]
    pop:    => @s[#@s]=nil
    push:(i)=> @s[#@s+1]=i




--automaton to execute the program
class Automaton
    
    new:(p,i,l,m)=>
        @t=Tape l,m --tape
        @s=Stack!   --stack
        @r=1        --read head
        @p=""       --program
        @i=i        --input
        @o=""       --output
        @e=nil      --error
        --strip useless chars of program
        for c in p\gmatch "[<>%+%-%[%]%.%,]+"
            @p..=c
        b=@check!
        if b~=nil
            @e="brackets mismatch at "..b
    
    --check for brackets mismatch
    check:=>
        s=Stack!
        for i=1,#@p
            if     @program(i)=='[' then s\push i
            elseif @program(i)==']'
                return i    if #s.s<=0
                s\pop!
        return s\top! if #s.s> 0 
        return nil
    
    --get char from input
    input:=>
        if @i==nil or @i=="" then return nil
        c1=@i\byte! --1st char of i
        @i=@i\sub 2 --remove 1st char
        return c1
    
    --output:   add char to output
    --program:  get instruction at 'n'
    --continue: continue execution
    
    output: (n)=> @o..=string.char n
    program:(n)=> @p\sub n,n
    continue:  => @r<=#@p and @e==nil
    
    --find matching bracket
    match:(b)=>
        m=1
        while m>0 and b<=#@p
            b+=1
            if     @program(b)=='[' then m+=1
            elseif @program(b)==']' then m-=1
        return b
    
    --opening bracket
    open:=>
     --jump to matching bracket
        if  (@t\out!)==0 then @r=@match @r
        else @s\push @r
        
    --closing bracket
    clos:=>
        if    (@t\out!)==0   then    @s\pop!
        elseif @s\top! ~=nil then @r=@s\top!
    
    --automaton's' execution step 
    step:=>
        switch @program @r
            when '<' then @t\mvL!
            when '>' then @t\mvR!
            when '-' then @t\decr!
            when '+' then @t\incr!
            when ',' then @t\ins  @input!
            when '.' then @output @t\out!
            when '[' then @open!
            when ']' then @clos!
        @r+=1
        if @t\unbound!
            @e="tape outbound !"




--display to see the execution
class Display
    
    new:(a,s=1,f=nil)=>
        @a=a    --automaton
        @s=s/60 --number of update per second
        @c=0    --counter
        @f=3    --display format of cells
        if     f=="hexadecimal" then @f=2
        elseif f=="character"   then @f=1
    
    --execute automaton all at once
    execute:=>
        while @a\continue!
            @a\step!
        @output!
    
    --update automaton at given frame rate
    update:=>
        if @a\continue!
            if @c<1 then @c+=@s
            else
                @c=0
                @a\step!
                @draw!
    
    --draw automaton state and output
    draw:=>
        cls!
        @tape    8, 2
        @program 8,12
        @output 4
        
    
    --draw the tape
    tape:(w=6,h=0,c=1,a=3)=>
        rect 0,h,240,w,c
        l=math.ceil (40/@f)*0.5
        p=(w-6)*0.5
        q=6*@f
        b=l-@a.t.h
        d=15
        if     @f==2 then d=6
        elseif @f==1 then d=3
        rect l*q-d,h,6*@f,w,a
        for i=@a.t.h-l,@a.t.h+l
            unless i<0
                c=15
                c=14 if i==@a.t.h
                v=@a.t.t[i] or 0
                if     @f==3 then v="%3d"\format v
                elseif @f==2 then v="%2x"\format v
                elseif @f==1 then v=string.char  v
                print v,(i+b)*q-d,h+p,c
    
    --draw the program
    program:(w=6,h=6,c=1,a=3)=>
        rect   0,h,240,w,c
        rect 117,h,  6,w,a
        p=(w-6)*0.5
        b=20-@a.r
        for i=@a.r-20,@a.r+20
            unless i<1
                c=15
                c=14 if i==@a.r
                v=@a\program i
                print v,(i+b)*6-2,h+p,c
    
    --print result of execution
    output:(s=0)=>
        i=s
        o=@a.o.."\n"
        --print each line
        for l in o\gmatch "[%S \t]*\n"
            print l,0,i*6
            i+=1
            break if i==21 --no more room
        --print error
        unless @a.e==nil
            print @a.e,0,130,6


--create automaton 'TM' using
--program : BF
--input   : IN
TM=Automaton BF,IN,128,nil


--create display 'DP' using
--automaton    : TM
--frame rate   : 30
--cell display : decimal
DP=Display TM,30,"decimal"


--execute the automaton and display it 
export TIC=->
    DP\update!


--http://moonscript.org/reference/
--http://moonscript.org/compiler/
--https://esolangs.org/wiki/Brainfuck
--http://zacstewart.com/2013/09/15/learning-cpp-a-brainfuck-interpreter.html

It is possible to change the width of the tapes and their colors. Also we can change the cell's display to see the values as decimal number, hexadecimal numbers or characters directly. This helps coding in BF a lot.

(3 edits)

Here the first program I made with TIC:

a BrainF**k interpreter in moonscript

--[moonscript]
--brainfuck interpreter by oSchyns
--v0.2.0


BF="++++ ++++"..
"[>+++++ +++++<-]"..
">++++.----- ----- -.--- ---."--..
--uncomment to test error output
--"<< force a tape outbound"


IN=""


--tape to perform computation
class Tape
    
    new:(l,m)=>
        @l=l  --cell limit
        @m=m  --loop the finite tape
        @t={} --tape
        @h=0  --read head
        --correct values
        @l-=1 if @l~=nil
        @m-=1 if @m~=nil
    
    --rhead out of the bounds of the tape
    unbound:=>
        if @m~=nil then return @h>@m
        @h<0
    
    --init nil cell to zero
    init:=> @t[@h]=0 if @t[@h]==nil
    
    --move read head to the left
    mvL:=>
        @h-=1
        if @m~=nil then if @h<0
            @h=@m
    
    --move read head to the right
    mvR:=>
        @h+=1
        if @m~=nil then if @h>@m
            @h=0
    
    --decreament cell
    decr:=>
        @init!
        @t[@h]-=1
        if @l~=nil then if @t[@h]<0
            @t[@h]=@l
    
    --increament cell
    incr:=>
        @init!
        @t[@h]+=1
        if @l~=nil then if @t[@h]>@l
            @t[@h]=0
    
    --ins: insert value in cell
    --out: get value from cell
    
    ins:(i)=> @t[@h]=i if i~=nil
    out:   => @t[@h]   or 0


--stack to hold indexes of brackets
class Stack
    new:    => @s={}
    top:    => @s[#@s]
    pop:    => @s[#@s]=nil
    push:(i)=> @s[#@s+1]=i




--automaton to execute the program
class Automaton
    
    new:(p,i,l,m)=>
        @t=Tape l,m --tape
        @s=Stack!   --stack
        @r=1        --read head
        @p=""       --program
        @i=i        --input
        @o=""       --output
        @e=nil      --error
        --strip useless chars of program
        for c in p\gmatch "[<>%+%-%[%]%.%,]+"
            @p..=c
        b=@check!
        if b~=nil
            @e="brackets mismatch at "..b
    
    --check for brackets mismatch
    check:=>
        s=Stack!
        for i=1,#@p
            if     @program(i)=='[' then s\push i
            elseif @program(i)==']'
                return i    if #s.s<=0
                s\pop!
        return s\top! if #s.s> 0 
        return nil
    
    --get char from input
    input:=>
        if @i==nil or @i=="" then return nil
        c1=@i\byte! --1st char of i
        @i=@i\sub 2 --remove 1st char
        return c1
    
    --output:   add char to output
    --program:  get instruction at 'n'
    --continue: continue execution
    
    output: (n)=> @o..=string.char(n)
    program:(n)=> @p\sub n,n
    continue:  => @r<=#@p and @e==nil
    
    --find matching bracket
    match:(b)=>
        m=1
        while m>0 and b<=#@p
            b+=1
            if     @program(b)=='[' then m+=1
            elseif @program(b)==']' then m-=1
        return b
    
    --opening bracket
    open:=>
     --jump to matching bracket
        if  (@t\out!)==0 then @r=@match @r
        else @s\push @r
        
    --closing bracket
    clos:=>
        if    (@t\out!)==0   then    @s\pop!
        elseif @s\top! ~=nil then @r=@s\top!
    
    --automaton's' execution step 
    step:=>
        switch @program @r
            when '<' then @t\mvL!
            when '>' then @t\mvR!
            when '-' then @t\decr!
            when '+' then @t\incr!
            when ',' then @t\ins  @input!
            when '.' then @output @t\out!
            when '[' then @open!
            when ']' then @clos!
        @r+=1
        if @t\unbound!
            @e="tape outbound !"


--create automaton 'TM' using
--program 'BF'
--input   'IN'
TM=Automaton BF,IN,128,nil


--execute 'TM'
while TM\continue!
    TM\step!


--print result of execution
cls!
i=0
TM.o..="\n"
--print each line
for o in TM.o\gmatch "[%S \t]*\n"
    print o,0,i*6
    i+=1
--print error
unless TM.e==nil
    print TM.e,0,130,6


export TIC=->


--http://moonscript.org/reference/
--http://moonscript.org/compiler/
--https://esolangs.org/wiki/Brainfuck
--http://zacstewart.com/2013/09/15/learning-cpp-a-br...

I also put some pages I used to code it.

Should I post it it the github wiki ?

Could it be possible to make the last character represent TAB instead of DEL.

Moonscript is based on indentation, and I had a bug caused by having a space rather than a TAB. It was quite annoying.

If I could mark tabs with a little dot, it would prevents those kind of mistakes.

This is amazing !

PICO-8 is dead to me !

Long live the TIC !

By own fonts and own color scheme, I meant allowing each user to customize their own TIC.

Like a tiny config file that change the default color palette on boot up (but keeping the 16 colors limitation).

As for the font, a special directory where you can place your custom font so it gets loaded on boot up.

But the font and the color scheme wouldn't be stored in the cartridges (well you can still change the color scheme by playing with the RAM). It would be just a setting for this particular user.

Both LUA and moonscript use ' -- ' as single line comment so maybe a way to allow the use of moonscript would be to use a special tag like "--[moonscript]".

- If the first line of the script as the exact tag "--[moonscript]" then all the code is in moonscript,

- otherwise it is in LUA

--[moonscript]
x = 10
if something
  local x
  x = 12
print x -- prints 10

Of course moonscript would be optional. TIC like PICO-8 rely on LUA to work.

moonscript is a language that gets converted into LUA to work. (similar to typescript -> javascript or coffeescript -> javascript or Scala -> Java, ...). As such all functions defined in LUA can be used in moonscript (no additional implementation work on that side). However you cannot do an include("moonscript") because the syntax is different than LUA. We should define a comment tag to specify the use of moonscript instead.

Moonscript as it is more complex than LUA shouldn't be the default choice, I agree. But moonscript is also interresting for TIC (and PICO-8) because it requires less lines to do the same things as LUA. And since the screen size is limited, it would help a lot on big project for advanced programmers.

TIC-80 community · Created a new topic Moonscript

Would it be a good idea to implement moonscript as an alternative Language for TIC ?

moonscript compiles into LUA, it implements classes and shorthand operators. And moonscript code require overall less characters than LUA code.

https://moonscript.org/

By that I mean I think it would be more interesting to implement moonscript into TIC rather than implementing shorthands into LUA like how it was done with PICO-8.

What do you think ?

I think we there should be a way to make your own fonts and your own color scheme.

Because I personaly prefer to have monospaced fonts.

But it is true that the fonts made by level27geek is cool.

Well there is three major keyboard layouts:

AZERTY -> French speaking regions

QWERTZ -> German speaking regions

QWERTY -> Everywhere else

AZERTY keyboards are always a mess to deal with. Sadly that is what most french users use.

The problem is that we need to do combinations such as:

AltGr+2 to get '~'

AltGr+3 to get '#'

AltGr+4 to get '{'

AltGr+5 to get '['

But in TIC, pressing AltGr+5 switch of workplace instead so some characters are writable only through ascii code.

There should be an option to disable such shortcuts and simply rely only on function keys F1,F2,F3,F4,F5 as they have no other uses.

Thank you.

More than just being able to specify where to install each game, I would like to choose where I want to install the itchio app itself.

I got a 120GB SSD which is just enough for the OS.

But I also have a 2TB HDD in which I put everything else.