Log In  

World's least talented polymath. Taller and funnier and person.

:: Unfold ::

I am working on a little shooter where players can move up and down a fixed track, and can aim a cannon to shoot a projectile at an angle. Ideally, this angle can run parallel to the track, but shouldn't intersect it.

I thought I had the math down, but I am running into an issue where the players' projectiles are able to intersect the track. It appears that, even though I constrain the angles that player cannons can point and fire, players seem to be able to extend and shoot a tiny bit beyond it. Strangely, a simple debug test that prints the angles indicates that they should be parallel to the track in these situations.

Angle constraint formulas:

--player 1 is on the left side, and aims right
    if p1.a<270 and p1.a>100 then
    if p1.a>90 and p1.a<270 then
--player 2 is on the right side, and aims left
    if p2.a<90 then
    if p2.a>270 then

Cannon aiming formulas:

    if btn(⬅️, p.c) then
     if p.a>360 then
    if btn(➡️, p.c) then
     if p.a<0 then

Have I found a bug with how PICO-8 does its circle math? Or have I erred somewhere? (It's probably the latter, but I can't see what I'm doing wrong.)

Cart #ponezabaka-0 | 2022-09-02 | Code ▽ | Embed ▽ | No License

P#116799 2022-09-02 22:31

:: Unfold ::

Cart #snailmaker-0 | 2022-07-30 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA

A silly little toy I threw together. Click your mouse to generate a bunch of randomly-colored snails that flee at varying speeds to the left and right of the screen.

P#115020 2022-07-30 18:44

:: Unfold ::

Cart #robosumo_1-0 | 2021-02-14 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA

I'm pleased to unveil my finished weekend project: Robosumo! Inspired by this entertaining video a friend showed me this week.

Special thanks to:

freds72, for helping me in the forums.
huulong, for an invaluable sprite rotation function.
NuSan, for a number of useful physics functions in Combo Pool.
Daisyfield's archive of public domain Japanese music.


It's sumo, but with robots! Ram your opponent and send them flying from the dohyō. Speed and finesse are your only weapons – but take care they're not turned against you.


  • Old-school competitive play: Local multiplayer for up to four players.
  • Configurable game length: Play one round, or one-hundred!
  • Single-player practice mode: Hone your skills in a stress-free sandbox.


  • 1-Player​: Score is not kept in 1-Player mode.
  • 2-Player​: Gain a point whenever the other player falls out of the ring.
  • 3- or 4-Player​: Gain a point if you landed the last hit on the player who fell out of the ring. (It is possible for a round to conclude with no points scored.)


Main Menu

  • UP/DOWN: Move cursor
  • LEFT/RIGHT: Toggle selected option
  • Z/X: Begin game

Game Screen

Player 1

  • UP: Move robot forward
  • DOWN: Move robot backward
  • LEFT/RIGHT: Rotate robot
  • Z/X: Restart game (practice mode only)

Player 2

  • E: Move robot forward
  • D: Move robot backward
  • S/F: Rotate robot

Players 3 and 4

Note: Joysticks or gamepads are required for 3- or 4-player games, as Pico-8 does not have native keyboard mappings for third- and fourth-player controllers.

  • UP: Move robot forward
  • DOWN: Move robot backward
  • LEFT/RIGHT: Rotate robot

Other Notes

Downloadable binaries for offline play are available for free on Robosumo's itch page.

EDITS: Removed list formatting from "Special Thanks" section, because it prevented the hyperlinks from displaying. Added a "Scoring" section.

P#87609 2021-02-14 01:37 ( Edited 2021-02-14 04:23)

:: Unfold ::

Hi everyone,

I'm working on a little robotic sumo game for a friend after seeing an IRL video about it. I decided to include a 4-player mode, because I like multiplayer games.

I want players to score only if they're the ones who knocked the player out of the arena when play is halted (basically like in Super Smash Bros), but I'm having trouble recording that information.

Here's the relevant code:

--main game loop
for p in all(players) do
 --other stuff

function check_hit(p)
 for o in all(players) do
  if circlehit(p,o) and  --Basic collision function.
   p.col~=o.col then     --This line is meant to keep players from hitting themselves.
    p.lasthit=o.col      --Here, "col" is the player's color, and "lasthit" is who last hit them.
  end                    --In another function, I award points to the player whose color
 end                     --matches the "lasthit" value of the ko'd player.

I need to prevent players from "hitting" themselves, because otherwise they would score when they're knocked from the ring. (If I remove the "p.col~=o.col" line, that's exactly what happens.)

But right now, scores don't register properly because of a bug with check_hit(p). My testing tells me there's something wrong with this function alone -- it's not recording a "lasthit" value as currently written. I'm not sure whether the problem is the "p.col~=o.col" comparison, or running a for loop within a for loop, or what.

Does anyone have a sense of what I've done wrong, or suggestions for doing this more efficiently? Thank you in advance for any and all advice.

P#87548 2021-02-12 20:43

:: Unfold ::

Hi everyone!

I am making a little game where you scare off crows to protect your vegetable garden:

I am trying to make the crows pick a vegetable to target when they spawn. I have a function that will make them chase down a point by entering its X and Y value. My problem is that I don't know how to extract the vegetables' X and Y values because of how I've set things up.

Every vegetable is decided at random at the game's outset, and stored inside another table, like so:

[note: dif is an integer, adding more vegetables at higher difficulties]

function setup()
 for i=1,dif do 
  add(vegetables, {
   [more variables and stuff you don't need to care about...]

My question is, how would I go about accessing the X and Y values for these? I have been trying something like this...


...but it has failed as a nil value every time.

Any advice is appreciated. Thanks for considering my problem!

EDIT: I classified the post incorrectly. Apologies!

P#85260 2020-12-10 22:59 ( Edited 2020-12-10 23:01)

:: Unfold ::

It's a long way from finished, but I now have something approximating a playable demo of a 1- to 4-player cart I've been working on.

Here is Star Shield for your... Uh... Enjoyment? Or whatever you want to do with it.


Defend your base against the stars' relentless assault by activating your left or right shield at the correct moment. Rack up a high score in single player, or be the last base standing in multiplayer!

Stars speed up after several deflections, and new stars appear at high point thresholds. Extra lives are awarded to particularly beleaguered players.


  • LEFT or (o): Activate left shield.
  • RIGHT or (x): Activate right shield.

For proper orientation, imagine yourself seated behind your station, looking into the circle.

  • Player 1: Red (South)
  • Player 2: Blue (North)
  • Player 3: Yellow (West)
  • Player 4: Green (East)

Cart #starshield_demo_v05-0 | 2020-03-30 | Code ▽ | Embed ▽ | No License

To-Do List

There is a lot that I'm still working on. Namely:

  • Moving stars along lines at intersections, rather than teleporting.
    • In an ideal world, the stars randomly decide whether to hop on a line when they pass them, and then randomly decide to travel counter/clockwise at the end of the line. I'm really struggling to come up with ways to go from circular movement to linear movement and back... The stars always fly off into space, never to be seen again!
    • The travel to the center circle is necessary for 3- and 4-player games, so that stars aren't trapped between two players.
  • Better shield activation windows.
    • BTNP allows an indefinite shield (defeating the point of the game), but BTN keeps it up way too briefly.
  • Displaying "empty" life markers when lives are lost.
  • Nicer title and menu screen.
  • Music and sounds.
  • Optimized maps and starting positions for 3-player games.
  • Much cleaner code!

I will update this thread as I progress.

Thanks for reading/playing!

P#74322 2020-03-30 04:23 ( Edited 2020-03-30 04:31)

:: Unfold ::

Hi everybody!

So, for a jam I'm far too unskilled to have considered, I'm putting together a little game where up to four players can pilot tiny ships and defend a fort. The ships can move about, and (eventually) shoot in the direction of a target that can be rotated around the ship by holding a button. It looks like this in practice:

(Enemies and animations forthcoming.)

Right now, I am attempting to optimize the code, because the player inputs eat a LOT of tokens in their current form. I currently have four different sets of inputs, one for each player, and each also moves a target that is specified as its own object (target1 with .x and .y, target2 with .x and .y, etc.). This is obviously no good, given the immense redundancies.

I think one could probably code a generic input function by making each target a property of its ship, using something like this:

function input(p)
  if btn(0,p.c) then p.x=p.x-1 p.targetx=p.targetx-1         --repositions player and target
   if p.x<0 then p.x=0 end                                   --prevents leaving the screen
   if p.targetx<0 then p.targetx=p.x+radius*cos(p.a/360) end
  if btn(1,p.c) then p.x=p.x+1 p.targetx=p.targetx+1         --repositions player and target
   if p.x>120 then p.x=120 end                               --prevents leaving the screen
   if p.targetx>120 then p.targetx=p.x+radius*cos(p.a/360) end
  if btn(2,p.c) then p.y=p.y-1 p.targety=p.targety-1         --repositions player and target
   if p.y<16 then p.y=16 end                                 --prevents moving into sandbar at top of screen
  if btn(3,p.c) then p.y=p.y+1 p.targety=p.targety+1         --repositions player and target
   if p.y>120 then p.y=120 end                               --prevents leaving the screen
   if p.targety>120+radius then p.targety=p.y+radius*sin(p.a/360) end
  if btn(4,p.c) then end                                     --fires bullet (to be implemented)
  if btn(5,p.c) then p.a+=target_speed                       --rotates target
   if p.a>360 then p.a=0                                     --resets target angle if needed
   elseif p.a<0 then p.a=360

Basically, as long as we specify the controller (c) associated with each player (p), we can use one function to dictate all player inputs. So, for each player, we have to put together a simple table of attributes.

And here is where my problem occurs: those stupid little targets.

Here's what I have tried to use for the first player's attribute table:

   targetx=p1.x+radius*cos(p1.a/360),  --PICO-8 doesn't like this line.
   targety=p1.y+radius*sin(p1.a/360),  --Or this one.

It seems PICO-8 doesn't accept putting p1.x, p1.y, and p1.a in those trig functions for p1.targetx and p1.targety. It raises an error, saying that they indicate an attempt to index a nil value. I guess I could just throw in a raw number for them? But I kind of need those variables, I think, since the location of the player's target must depend on the location of the player's ship.

TL;DR: A table isn't working like my noob brain would expect, and I have three questions:

  • Why are p1.x, p1.y, and p1.a nil values, if I already provide values for them in the table?
  • How else might I define targetx and targety, such that they remain properties of p1?
  • If the method I've proposed is stupid, what might you suggest as a workaround?
P#73758 2020-03-21 18:53

:: Unfold ::

I'm having an issue where it seems like I absolutely cannot pass an argument to a function, no matter what I do.

For starters, I am using doc_robs' famous hitbox function:

  function player_hit(x1,y1,w1,h1,
   local hit=false
   local xs=w1/2+w2/2
   local ys=h1/2+h2/2
   local xd=abs((x1+(w1/2))-(x2+(w2/2)))
   local yd=abs((y1+(h1/2))-(y2+(h2/2)))
   if xd<xs and yd<ys then
   return hit

So far, so good, right? Then I pass the following arguments along to it from another function:

  if player_hit(p1.x,p1.y,pw,ph,star1.x,star1.y,sw,sh) then
  --stuff happens in here

All of the values in the preceding if statement are defined at _init(). The values pw, ph, sw, and sh are all 2, defined as global variables. The p1 and star1 values come from tables.

But every time I run my program, this error occurs:

   local xs=w1/2+w2/2
Attempt to perform arithmetic on local 'w1' (a nil value)

Now, I can't find the reason why w1 registers as nil. The value pw (2) should be subbed in for it, since it's being provided in the function call.

Strangely, the same error occurs even if I manually type "2" in place of pw in the player_hit() call.

P#74058 2020-03-19 23:20

:: Unfold ::

If you grew up with the NES, you remember that their basslines had a certain "snappiness" to them (for lack of a better word). Here are two of my favorite examples:


Anyway, I've been trying to mimic that type of bass as closely as I can in my PICO-8 carts, but I haven't quite hit the mark yet.

Does anyone have instrument/effect suggestions for achieving this kind of sound?

P#73870 2020-03-19 18:22

:: Unfold ::

This is probably a ludicrously simple thing that I never learned, so please forgive me in advance.

I'm trying to write a function that checks whether a thing (star1) moving in a circle intersects with any of four lines (four_p_lineX) that connect to the circle. The best way I can think to do this is to make the function check whether the X and Y coordinates of star1 match the X and Y coordinates of any of the line endpoints.

The thing is, PICO-8 doesn't like what I've written:

 function check_direction()
  local s1switch=flr(rnd(1))   --You wonderful forum people can ignore this part.
  if (star1.x,star1.y)==(four_p_line1.x1,four_p_line1.y1) or
                        (four_p_line1.x2,four_p_line1.y2) or
                        (four_p_line2.x1,four_p_line2.y1) or
                        (four_p_line2.x2,four_p_line2.y2) or
                        (four_p_line3.x1,four_p_line3.y1) or
                        (four_p_line3.x2,four_p_line3.y2) or
                        (four_p_line4.x1,four_p_line4.y1) or
                        (four_p_line4.x2,four_p_line4.y2) then
   if s1switch==1 then         --Ignore this, too.

The above code produces the following syntax error:

 if (star1.x,star1.y)==(four_p_line1.x1,four_p_line1.y1) or
')' expected near ','

I can't really figure out what the error is telling me. Is it as simple as me forgetting some punctuation, or can I not make the comparison I'm trying to make?

P#74024 2020-03-18 01:11

:: Unfold ::

Hi everyone!

I'm hard at work on a 1-4 player cart, but I've run into a snag when it comes to moving a sprite around in a circle.

I more or less have the movement down (thanks to tonechild), but it looks like the wrong part of the sprite is tracing the circle I want:

(Please excuse the incomplete graphics and such.)

It appears that the upper-left corner of the sprite is tracing the circle here, when I'd really prefer something closer to the center of the sprite. Is there a way to make this happen? Or, if not, is there a workaround any of you might recommend?

Here are the relevant points of my (messy) code. You'll notice the star is able to "trace" the track because it uses the same variables I used to draw the circle.

 game_over=false   --determines that a solo player has lost
 player_win=false  --determines that a player won in multiplayer
 radius1=55  --determines outer circle size
 radius2=25  --determines inner circle size
 originx=63  --center of screen/track
 originy=63  --center of screen/track

 --star 1 data
--moves stars along track
 function move_stars()
  --moves star 1
   if star1.angle>360 then star1.angle=0
   elseif star1.angle<0 then star1.angle=360
 --draws track that stars follow
 function draw_track()

Thank you for reading, and for considering the problem! I promise I'll be a better forum participant in the near future, when I know a bit more about this whole Lua thing.

P#73965 2020-03-16 01:54

:: Unfold ::

With many thanks to packbat for helping me in the forum, I can finally say my first real cart is complete!


Cart #bastard_squash_v1-0 | 2020-03-13 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA

I don't have any training in programming or math, so this isn't as impressive as most debut carts. Still, we all have to start somewhere! I hope you find something to enjoy in it. Also, don't mind the unused sound samples, and general code inelegance...


Have you ever thought your game of squash needed to hate you a little more? Then do I have a cart for you!

Your paddle shrinks with each successive hit. Past certain point thresholds, it also begins to creep toward the ceiling. Extra lives are granted every 300 points, because I love you, even if my game doesn't.


  • LEFT/RIGHT: Move the paddle
  • X (x): Hold to increase paddle speed
  • Z (o): Hold to decrease paddle speed

(EDIT: Added link to packbat's user profile for better crediting.)

P#73884 2020-03-13 15:33 ( Edited 2020-03-13 15:35)

:: Unfold ::

I'm looking for some advice on how to grant the player extra lives after the score crosses a certain point interval.

I've checked a few carts that do this, but I'm not able to make sense of the functions they use, and I was wondering whether anybody had a simple method handy.

At the moment, I only have a brute-force method. My cart uses two straightforward variables: "lives" counts the player's lives, and "score" counts the score. Let's say I want to give the player an extra life for every 300 points they score. Right now, I only have this:

function gainlife()
 if score=300 then
 elseif score=600 then
 elseif score=900 then

It kinda works (assuming the player loses interest in the game after around 1,000 points). But I figure there HAS to be a way to capture the interval in a neater function. Unfortunately, my stupid brain can't figure it out!

Thank you for whatever wisdom you have to share.

P#73869 2020-03-13 04:00

:: Unfold ::

Once again using Dylan Bennett's Game Development with PICO-8 as the backbone, I've rolled out a new project based on his "Lander" recipe. Presenting Red Planet Mission:

Cart #yasodahiba-0 | 2020-03-11 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA

I've tweaked the sprites, added a start screen (with art!), and managed to put together menu and gameplay themes.

I couldn't figure out how to randomize the star background each time you start up the game, but I'll keep trying.

It's quite exciting to have put all the features of PICO-8 to use in a cart! The next step is to do something using my own code next time.

P#73836 2020-03-11 22:03

:: Unfold ::

Hi everybody,

I'm having some difficulty figuring out how to solve a problem with how PICO-8 handles music, and I was wondering whether any of you out there could help me.

Let's say I have a few SFX files that I intend to collate into a music composition for my game, like in the following image:

Notice that there are a few unused measures for this clip. Let's assume that I have several other clips that are similarly structured.

When I try to string these together in the music editor, the system plays all those empty measures like they are rests. But what I would really like to happen is for the music to "jump" directly from the end of the clip to the beginning of the next one.

Is there a way to make this happen?

Thank you for any and all input!

P#73814 2020-03-11 04:19

:: Unfold ::

I sampled PICO-8 for the first time this weekend. Being a rank novice at programming, I have little idea of what I'm doing. Luckily, given the abundance of PICO-8 resources here and elsewhere, I'm learning quickly!

Here is my first attempt at a game: a barely modified version of Cave Diver from Dylan Bennett's Game Development with PICO-8. I give you: Bat Cave!

Cart #dasanidez-0 | 2020-03-09 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA

It leaves a bit to be desired as a "game," but in terms of newbie accomplishments, I'm pretty proud of figuring out how to insert a title screen. That will certainly come in handy later.

Here's to producing better games in the future!

P#73779 2020-03-09 03:57 ( Edited 2020-03-09 03:58)

Follow Lexaloffle:          
Generated 2023-06-03 15:39:22 | 0.083s | Q:42