Log In  
Log In  

@freds72

Follow
Follow

Old enough to have known the golden age of Amstrad and Amiga ;)
Still own a few Tilt and Joystick magazine (yeah, I am french).
Professional software architect, hobbyist gamedev.

Game & experiments repo: https://github.com/freds72

Twitter account: https://twitter.com/FSouchu

I am writing data to a p8 file from a Python program - format for 0x0-0x3200 ROM range is ok.
Issue is sfx section - each sfx (68 bytes) is actually written as 84 bytes (??) with empty bits left and right.
I have no clue what is the masking/bitshifting/... logic between my input value and the resulting p8 string.

Example:

poke4(0x3200,0x1234.5678)
cstore()

produces:

__sfx__
000100003813534011000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

wtf??

P#64268 2019-05-09 18:44 ( Edited 2019-05-09 18:49)

Case solved: issue was triggered by one of my USB sticks constantly sending inputs

When exporting Tiny Sim, some keys are stuck:

P#64164 2019-05-03 14:25 ( Edited 2019-05-04 09:17)

Cart [#numakunawa-0#] | Code | 2019-04-08 | No License | Embed
21

FPS demo cart as an answer to @MBoffin April 1st Twitter joke.
Stay tuned for technical details.

P#63343 2019-04-08 21:27

Cart [#doyusuyepo-0#] | Code | 2019-05-04 | No License | Embed
17

Project started following a question on 3d clipping on this forum and quickly spiraled into a full blown 3d renderer with support for real-time shadows and camera space clipping :/

Shadows are calculated in real-time by extruding a shadow volume from each lit face.
Resulting polygons are added to the face and rendered/sorted with the face.

The shadows are globals e.g. self-shadowing is supported, see torus scene.

Performance-wise this is bordering what pico can support, as many clipping operations are required to generate shadow polygons. There is room for optimization (vertex cache, smart selection of clipping planes) left to the reader!

Sources

Project (including how to add custom 3d models) is available here: github

Acknowledgements:

  • 3d papers from the 70s/80s are pure gold!
  • trifill function from @p01

Update 1.1

  • fixed polygon gaps (using correct middle screen position + ceil)
P#60772 2019-01-12 14:38 ( Edited 2019-05-04 12:54)

How to reproduce:

  • go to a game page
  • launch game
  • go to comment section
  • type some text

Bug: nothing appears (input is captured by pico)

Workaround: refresh the page / don't launch game before posting comments.

P#59908 2018-12-11 21:38 ( Edited 2018-12-11 21:38)

Since forum updates, new gif uploads are rendered as broken links.
See: https://www.lexaloffle.com/bbs/?pid=59400#p

P#59537 2018-12-01 15:11

Cart [#55974#] | Code | 2018-08-31 | License: CC4-BY-NC-SA | Embed
33

Be a X-Wing pilot!

Take a seat in the most advanced fighter of the galaxy. Fight against the evil empire!
Use proton torpedo to quickly dismiss enemy forces or your 4 blasters (aiming skill required).
Go through 4 epic missions, from space to Deathstar and back.

Flight Manual

Copyright Notice

Starwars logo/music/... credits to their respective owners. Don't sue me :/

Dev Log

This is a demake of the X68000 Attack of the Deathstar game, (kind of) complete with space/ground/trench missions.
This version departs from the original with a less arcade/grinding gameplay.

The un-minified version can be found (as usual) on my Github page (includes all 3d assets).

Tie Fighters

All flying NPCs are following boids behavior (seek, avoid, follow) and are really a blast to watch in pack (imho)!
Baddies will try to get on your six to fry good old r2d2 :/

Proton Torpedo

Proton flight path is following Proportional Navigation rules. Gives a nice interception path (and the math is cool :)

3d Engine

Engine is a edge renderer (wireframe only as you certainly noticed!). It supports faces with an arbitrary number of edges to reduce visual cluter and achieve good performance.

Face culling is using object-space culling, the normal.point constant is pre-calculated when model is loaded.

Quaternions functions ported from ThreeJS.

3d Sound

(sort of...) Sound volume is changed at runtime according to sound emitter location, using the PICO-8 "feature" that sfx can be modified without impacting currently playing sound.
Note: sfx 63 is reserved for that use.

Software Pipeline

3d assets are modeled in Blender, exported in sprite/map format using a Python exporter .

Models are unpacked from spritesheet/map memory at startup and made available in a global table.

All game data are expressed as JSON strings, supporting references to global functions. Ex:

_g.update_player=function(self)
  self.x+=1
  self.y+=0.5
end()
local player=json_parse('{"x":0,"y":0,"update":"update_player"}')
-- works!
player:update()

Mini json parser from Tyler Neylon: lua JSON parser

Code is minified using picotool.
Music lifted from "public" MIDI files, simplified and converted with midi2pico.

Changelog

1.0:

  • Initial public version
  • Bug: not able to restart after gameover (will be fixed soon)

1.1:

  • change: redone control scheme (flat turn, optional roll)
  • change: removed boost
  • change: laser auto lock
  • change: difficulty curve
  • fixed: NPC flight AI
  • fixed: torpedo aiming

1.2:

  • added: menu to switch view
  • changed: turret & tie fire lead (+ random chance to miss)
  • changed: tie fighter difficulty ramp up
  • fixed: random hit on NPC (distance function overflow)
  • fixed: reworked trench to keep 60 fps
  • removed: in-game help
P#53727 2018-06-23 09:45 ( Edited 2018-10-18 21:17)

Hi,
Coroutines are an essential part of my game engines.
However, I don't get how I can do both:

  • raise an error when something bad happens
  • silently handle proper coroutine termination

coresume returns a pair (is running,exception).
Thing is exception is set even during normal termination!!
note: costatus doesn't help as it immediately flips to "dead" when the coroutine crashes.

Something like that doesn't work, e.g. I get an assert even after genuine termination:

local co
function _init()
    co=cocreate(function()
        for i=1,10 do
            yield()
        end
               -- syntax error test
           -- i=k/10
    end)
end

function _update()
    if co then
     local r,e=coresume(co)
     print(costatus(co))
     if not r then
        if(e) assert(r,e)
        -- never reached
        co=nil
     end
    end
end
P#53201 2018-06-02 04:48 ( Edited 2018-06-02 15:26)

Cart [#52460#] | Code | 2018-05-06 | License: CC4-BY-NC-SA | Embed
11

As a temporary side project, I hastily ported Randy Gaul ImpulseEngine to pico-8/LUA.

Usage

Requires a mouse

  • left mouse button: create a random shape at mouse cursor or drag shapes
  • right mouse button: show/hide world or body options
  • button c: show/hide debug information

Dev Log

The physic engine is a direct port from Randy Gaul's work, detailled in a series of articles:
How to Create a Custom 2D Physics Engine

My contribution is mostly on a clean 2d vector and 2x2 matrix object oriented library.
It makes vector/matrix math very concise to work (and easy to port from C++ code!):

local v1,v2=vec(3,4),vec(5,6)
local v3=v1+v2
-- rotation matrix
local m=mat:make_r(0.4)
local r=m*v3

Note: I don't plan to expand the library beyond this demo, feel free to make a game out of it!

The cart now include a context menu that could be fairly easily reused for other carts.

Missing Features:

  • Optimisation pass (currently supports ~4/5 objects max)

Change Log

1.0:

  • initial revision

1.2:

  • added: support for circles

1.3:

  • fixed: force reset
  • changed: left click now creates a new body
  • added: right click menu to control world or object settings
P#52222 2018-05-01 08:32 ( Edited 2018-05-06 16:44)

Cart [#50248#] | Code | 2018-03-11 | License: CC4-BY-NC-SA | Embed
16

Anti-Aliased Asteroids

Hastily crafted Asteroids clone complementary of the anti-aliased line thead:
https://www.lexaloffle.com/bbs/?tid=30810

Changelog


1.3:

  • Added: Teleport ('c' button)! Up to 3 chances (sort of...) to get out of trouble
  • Changed: inertia cranked up, use your thrusters!
  • Changed: safe time is now 2s
  • Changed: thrust is now 'up' only
  • Fixed: Saucer Invasion!

1.2:

  • Fixed: incorrect font rendering
  • Fixed: incorrect high score message on game over
  • Changed: reduced number of rocks to 4

1.1:

  • Fixed: crash with dead player
  • Changed: multiple rocks types
  • Added: saucer!
  • Added: highscore (saved in cart data)
  • Added: multiple CRT effects (enjoy @Felice!)
  • Bug: couple of chars incorrectly rendered

1.0f: temp. fix by @Felice (tks!)

1.0: initial release (did not work)

Tech. Details

Not much really - using bits of my Pico 8 "game toolkit":

  • anti-aliased circle fill (using mid-point error for the shading)
  • multiple "CRT" shaders (find out how to switch between them!)
  • a couple of future functions using yield
  • vector font rendering

Credits

  • Felice: anti-aliased line optimisation genius!
  • Trammell Hudson: Asteroids font (https://trmm.net/Asteroids_font)
  • Atari: for the art cover (my lawers are on the copyright case :)
P#49676 2018-02-25 17:01 ( Edited 2018-08-21 20:55)

Cart [#49509#] | Code | 2018-02-22 | License: CC4-BY-NC-SA | Embed
11

This cart is just to provoke @zep (or any other true Pico-8 genius) into releasing a fast anti-aliasing demo cart!

The code is a LUA port of that paper:
http://jamesarich.weebly.com/uploads/1/4/0/3/14035069/480xprojectreport.pdf

Note: I don't get how an incremental line drawing routine (a la Bresenham) can be that slow (compared to the native version). 270% cpu usage for 16 lines sigh...

P#49510 2018-02-22 15:16 ( Edited 2018-02-28 07:42)

Cart [#50452#] | Code | 2018-03-15 | License: CC4-BY-NC-SA | Embed
38

Suzie and Bob are trapped in a merciless world. Can you fight your way out?

Gameplay Elements

  • Random maps
  • Multiple biomes

  • Multiple enemies
  • Multiple weapons (but one at a time!)
  • Loop-based difficulty
  • Supports keyboard/mouse

Controls


Keyboard:

  • arrow keys: move & gun direction
  • bttn 1: fire & lock direction
  • bttn 2: pick up weapon

Mouse (selected in option menu):

  • arrow keys: move
  • mouse: gun direction
  • left click: fire
  • right click: pick up weapon

Note: any resemblance with a famous Vlambeer game must be purely accidental...

Changelog


1.2:

  • fixed: woobly sprites
  • fixed: actors stuck on corners
  • fixed: warp in/out effect
  • changed: impact feedback
  • changed: health upgrade on loop

1.1:

  • fixed: unexpected god mode
  • fixed: boss hp
  • fixed: boss attack
  • changed: tweaked game speed
  • change:balanced high level gameplay (loop)

1.0:

  • preview version

Dev Log


2nd finished game (last was Thunderblade). Took 4 months to complete & refine.
Un-minified source available on Github:
freds72/pico8/carts/nuke.p8

Tech Highlights
JSon Rules!
All entities (actors, weapons, particles, levels) defined using json (worth 3500 tokens!). A lightweight parser (450 tokens) converts strings into lua tables.

Entities are created using a parent template with support for:

  • lua references
  • random values
  • method & attributes override

Rotating Sprites
Player weapon (and couple of other sprites) are rotated in real-time using an optimized sprite routine. It is fast enough to allow ~10+ sprites on screen (before tanking FPS!)

Performance
An actor map is maintained each frame. It allows immediate bullet/actors lookup.
Only player/npc collisions are checked to ensure player cannot zip through enemies.

A-* path is refreshed for a single npc per frame. It ensures a large number of npc’s can be created without too much cpu stress.

Sprites are added to buckets matching their y pixel coordinate.
Saves both cpu and tokens as no global sort is required :]

Toolchain
Cart is minified using picotool (19k compressed). All json attributes are replaced by their short equivalent using output from minification script:
cat nuke.p8 | minify | replace > nuke_mini.p8

Missing In Action:

  • RPG aspects (upgrades/xp/abilities...)
  • Good music (for total lack of musical skills!!)
  • Scoreboard

Credits

P#48516 2018-01-24 15:49 ( Edited 2018-03-15 21:52)

While playing with the very handy picotool utility, I discovered that simply removing tabs on my well formatted code I was able to save 813 compressed bytes!!!

Seriously???

I've spent days trying to remove code, reshuffle stuff to save 50-100 bytes and simply making my code unreadable beats any of these optimizations??

:_[

P#46074 2017-11-09 16:07 ( Edited 2017-11-09 21:51)

I can get Windows, Linux and Raspberry updates but what about PocketCHIP?
My mobile development platform can no longer run a lot of the newly published games :[

P#46017 2017-11-08 16:50 ( Edited 2018-02-19 17:10)

Cart [#44887#] | Code | 2017-10-03 | License: CC4-BY-NC-SA | Embed
13

Back 30 years ago, After Burner and Thunderblade ruled the arcades.
As a kid, I only had an Amiga and near zero coding skills to produce very (very) weak clones.
Now a seasoned programmer with the mighty power of PICO-8, I can beat a Sega X board!
Well, err...:

Credits
• Chris Butler (player + tank sprites lifted from the C64 1989 version)
• gamax92 for midi to pico-8 program
• dw817 (david w) for image decompression code (http://writerscafe.org/dw817)
• pico-8 community

What's Missing
• gameplay tweaking...
• levels 2,3,4,5
• gazillions of buildings on screen!

Tech Details

Map:
Drawn using sprite sheet (2), you can tweak the level using colors:
4: tank
6,7,13: building
8: enemy helicopter
9: Battleship boss
10: swtich to chase mode
11: switch to top-down mode
15: end_game (use carrefully!)

Title screen:
Title image is loaded from a stringified image, decompression done 'asynchronously' with yield.

Main screen:

Buildings are mostly drawn with many rectfill using a big checkerboard pattern to simulate windows/floors.

Everything is z-sorted (w actually ;) before being drawn. This 'zbuffer' is in charge of drawing every asset.

Game screen manager:
A light version of what I've extensively used during my XNA period. Allows nice decoupling between game loop and other loops (title, game over).

Coroutines:
Used only for rare events (like player dying) to easily control animation and state changes.

Lessons Learned
• PICO-8 is a fantastic platform. Forces you to keep things simple (say that to my dozen or so failed Unity attempts...)
• token count is everything
• Coroutines are unfortunately too slow to be used in the core game loop
• Throw OOP techniques out. The nice class:method() construct eats up too many tokens - had to rewrite half of the code to stays within the limits :[
• bnot-cheating the platform is way too easy (but resisted against!)
• Did I say token count is everything?

P#44889 2017-10-03 16:02 ( Edited 2017-10-20 06:38)

Working on my game, I often find myself wondering how much cpu such or such construct uses.
I do my benchmarks using stat(1).
Issue is, my measures are all over the place according to the number of samples :[

Ex: Let's bench band vs. % and shr vs / @ 100 calcs/update

Good, % is almost free, / is slightly better than shr
Let's try 200:

Hu? shr is now better than /

Push it to 300:

Back to "normal"

400:

WTF?

How come number of samples for a given run is turning results upside down?
Note: if I push number of iterator further, I tend to have stable results - but who's performing 5000% per update cycle?!?
On top of that, @zep, we should be provided with op cost of basic operations (similar to cpu specs).

Reference code:

function bench(name,n,fn)
    local t0=stat(1)
    for i=1,n do
        fn(i)
    end
    return {name,(stat(1)-t0)}
end
function stat2pct(s)
    return flr(1000*s)/10
end
function bench_draw(name1,stat1,name2,stat2,y)
    print(name1.." vs. "..name2,1,y,7)
    y+=6
    local total=stat1+stat2
    local pct1,pct2=stat1/total,stat2/total
    local c1,c2=8,11
    if(stat1<stat2) c1=11 c2=8
    local x=flr(128*pct1)
    rectfill(0,y,x+1,y+6,c1)
    x+=1
    print(stat2pct(stat1),x/2,y+1,0)
    local x2=128*pct2
    local msgx2=x+x2/2
    if(x2<1) then
        x=127 x2=127 msgx2=120
    end
    rectfill(x,y,x+x2,y+6,c2)
    print(stat2pct(stat2),msgx2,y+1,0)
    y+=8    
    return y
end

local res={}
local n=100
function _update60()
    if(btnp(0)) n-=100
    if(btnp(1)) n+=100
    n=max(n,100)

    res={}
    add(res,bench("band",n,function()
        j=band(546,127)
    end))
    add(res,bench("%",n,function()
        j=546%128
    end))

    add(res,bench("shr",n,function()
        j=90/8
    end))
    add(res,bench("/",n,function()
        j=shr(90,3)
    end))
end

function _draw()
    cls(0)

    rectfill(0,0,127,6,1)
    print(n.." iterations - \139\145 to change",1,1,7)

    local y=9
    for i=1,#res,2 do
        y=bench_draw(res[i][1],res[i][2],res[i+1][1],res[i+1][2],y)
    end
end
P#43888 2017-09-03 05:12 ( Edited 2017-09-09 13:27)

About | Contact | Updates | Terms of Use
Follow Lexaloffle:        
Generated 2019-05-26 00:21 | 0.161s | 4194k | Q:130