I'm trying to figure out how to make my camera area shift based on when the player is a certain distance from a center zone. I don't want my player in the middle of the camera all the time. I want them to "push" the camera zone around as they get to the edges...but then push the camera back when they hit a certain distance in the camera zone.
That's confusing, maybe...how about this...
There's a 128x128 "free zone" where the player moves around freely. They go right and when they hit x128 it switches to camera mode and the player can keep moving right until the edge of the world. Once they get to the edge, they need to go back to the left, but on the way back the camera needs to move when they hit the half way point of the viewport they're in...as opposed to moving the camera when they hit the left edge of the camera viewport.
It's like a lot of the old NES games where you'd move forward once your character hit mid-point, but if they turned around the camera wouldn't move anymore. Kind of like Metroid was.
Sorry if that's still as clear as mud...but if you think you know what I'm trying to accomplish, any insight or thoughts are appreciated. I know camera() is the key but everything I try to calculate doesn't work out...
CHOMP
Chomp is a Pico-8 game were you have to chomp down pellets and other fruits as they keep coming faster and faster!
Unlock the two harder modes by reaching 10000 points in the previous mode!
In menus, use circle and cross keys ('z' and 'x' on keyboard) and the arrow keys to navigate.
Once a game launched, press any Pico-8 button to CHOMP.
The game is controller compatible.
Do share your highscores as well as what you think of the game in the comments! :D
If you really like the game, please do consider supporting it on itch! All income goes into making more games!!

The code below should draw 10 squares, there is only one variable that define the size (b.s in _init), but sometimes some squares appear with a width different of the height. I don't know if its a bug, or I'm using rectifll in the wrong way.
blocks={}
function _init()
for x=1,10 do
local b={}
b.x=rnd(100)
b.y=rnd(100)
b.s=rnd(15)
add(blocks,b)
end
end
function _draw()
cls()
for b in all(blocks) do
rectfill(b.x,b.y,b.x+b.s,b.y+b.s,4)
end
end
|

Wrapped up my second game, and this time it's an actual game! glares at Blocksy
PICOMMANDO
A top down twin-"stick" shooter, since I felt that wasn't a very active genre around here. Utilizes P1 controls (arrows) for movement, and P2 controls (ESDF) for shooting. This may change in the future, specifically when I get a PocketCHIP and need to figure out what layout will work best there.
Zombies will come running at you from the entrances and from the corners at various speeds and in various numbers. Firing excessively will drain your clock, but successfully killing a zombie will restore some time.
Features high score saving to cartdata to give some sort of goal/objective. My high is around 600 on this build, a no-prize for whoever beats it first.
I consider this 'finished' but I'm interested in feedback on the gameplay loop, i.e. is it too hard, are the zombies too fast, is there enough time on the clock, etc as well as feedback on the controls.
Enjoy!
(p.s. this is my first stab at making any sort of music in any capacity, ever. hopefully it's not too annoying)
(p.p.s. before anyone says so, yes, I know, my main function loop got completely out of hand and should be broken up into about 40 or so actual functions. This was my big lesson learned to apply to Game #3 lol. So use the source however you like but PLEASE try not to learn anything from it)

If you'd like to take part in P8JAM2, please select one or more themes by clicking on the PICO-8 star next to it (you need to be logged in). You can change it anytime before the 24h voting phase ends -- at 00:00 PST on Saturday the 21st. Check out the jam thread for more details.
Edit: times's up! The winning theme is Chain Reaction. You have 9 days! Good luck!

Sat down for my first hour of learning both LUA and Pico-8.
This was just to practice parts of the software and get things up on the screen.
Also to test out saving and uploading a cart.
Next I plan to:
- Research the best way to handle multiple moving objects.
- Add controls
- Add weapons
- Detect collisions
- Game states (start, win, lose)
This is a work in progress tool, which currently allow you to look at the Pico-8 memory content.
It's really crude but do it's job:
Left will substract 0x10 to the current address, Right will add 0x100, UP will remove 0x100, Down add 0x100.
The display is in three parts, the top that show the top address, the middle with alternating bluish/pink that show a gris of 16*16 bytes from memory starting from address, and the value are show in Hexadecimal
The bottom part show the first half of the same memory as in hexadecimal, but will display the values as character and not hex, useful to look for string!
I got Splore to crash all of Pico-8 on Mac OS X 10.11.5 while browsing the local folder. The crash occurs as soon as I select a specific cart in my root folder. I was able to reproduce this by moving the poison cart to a subfolder, as well as clearing the root folder from everything except the cart.
Here's the cart, named test_jelpi_fmt.p8: https://dl.dropboxusercontent.com/u/264756/test_jelpi_fmt.p8
This is the .p8 of Jelpi run through the picotool minifier. I can load and run it successfully with the "load" command.
Mac OS X crash report:

Hi ZEP,
I'm going to make a Pico-8 stand for a retrogaming convention later this year, and I was thinking on how to organise it.
And I would really want to use Splore as the browser for existing cart, especially because it works really well in my arcade cabinet.
But as you know apart from the "local folder" tab, Splore can only be used when the computer is online and have access to your website.
As Pico-8 is, I think, using standard web services for Splore, it would be nice if the base URL could be changed in the config, instead of using fake DNS, for such a (unusual) use.
But that would also mean that the BBS protocol should be documented in a way too.
My idea for the stand is to have multiple devices connected together on a network (wired/wireless doesn't matter), so I can have access to all the computer (which will mostly be rPi and probably my CHIP) so they could share data, and as Splore is a really good browser for that, it would be really nice to have access to it.
By the way, it would be nice too to have a way to directly push a new cart from Pico-8 and not have to rely on the web browser, but that's another problem.
As my goal is really to try to make the cluster of Pico-8 to be autonomous from the internet, this functionality will allow me to let people share their production on all the pico8 available using the offline bbs, without the need of having a web browser running on the Pi.
Especially as I will want to make it run Pico-8 directly and to not have access to anything else, like if it was a real console hardware.
I think I may add more about this project on my "blog" part here with the advancement of this project as I want it to be useful for other people making event around Pico-8
Cheers
I've been working on a tile based puzzle game recently and to make things easy initially I setup random generating levels. While this helped me get through adding and testing the mechanics and my code I realised that some times in testing I'd get a level I might want to play again but as it was one of eight million I wasn't likely to generate it again.
So I realised that I would need to create Level IDs and a system for inputting them. This is my first attempt at a very basic input and the screen displays the output too that I would feed into some variables in my game to get back to that challenging level.
As a complete novice any feedback or improvements are greatly appreciated. My known bugs so far are not knowing a slick method to stop the highlight moving off either end of the row and not being able to limit the range of letters (you can go down from A etc.)
--basic levelid i/o
--by lorcav
function _init()
cls()
hlight={}
hlight.x=32
hlspr=29
l1=1
l2=1
l3=1
l4=1
l5=1
l6=1
l7=1
actsprpos=1
end
function _update()
cls()
map (0,0,0,0,16,8)
move(hlight)
spr(hlspr,hlight.x,40)
spr(30,hlight.x,24)
spr(l1,32,32)
spr(l2,40,32)
spr(l3,48,32)
spr(l4,56,32)
spr(l5,64,32)
spr(l6,72,32)
spr(l7,80,32)
movebound()
end
function move()
if(btnp(0)) --left
then
hlight.x-=8
actsprpos-=1
end
if(btnp(1))--right
then
hlight.x+=8
actsprpos+=1
end
if(btnp(2))--up
then
entryup()
end
if(btnp(3))--down
then
entrydown()
end
if(btnp(4))--confirm
then
end
end
function entryup()
if actsprpos==1
then l1+=1
end
if actsprpos==2
then l2+=1
end
if actsprpos==3
then l3+=1
end
if actsprpos==4
then l4+=1
end
if actsprpos==5
then l5+=1
end
if actsprpos==6
then l6+=1
end
if actsprpos==7
then l7+=1
end
end
function entrydown()
if actsprpos==1
then l1-=1
end
if actsprpos==2
then l2-=1
end
if actsprpos==3
then l3-=1
end
if actsprpos==4
then l4-=1
end
if actsprpos==5
then l5-=1
end
if actsprpos==6
then l6-=1
end
if actsprpos==7
then l7-=1
end
end
function movebound()
if hlight.x>=81 then
hlight.x=32
actsprpos=1
end
if hlight.x<=31 then
hlight.x=80
actsprpos=7
end
if l1>=14 then l1=1
end
end
function _draw()
print ("please enter level id",19,44,10)
print (l1,35,52,8)
print (l2,43,52,8)
print (l3,51,52,8)
print (l4,59,52,8)
print (l5,67,52,8)
print (l6,75,52,8)
print (l7,83,52,8)
end
|

Hi Aviator!
This is a tiny flight simulator based on a Cessna-172R with a G1000 glass cockpit. (This is the plane I fly in real life, so I thought it would be a challenge to see if it can be done with Pico-8.)
The flight model is not based on theory but on my observations as a pilot. I have to say that it's quite good ;-) Within the limits of Pico-8 it quite feels like the real thing.
Disclaimer: while I created the instruments and the flight model, the majority of the programming work was done by @freds72, including 3D outside view, code structure, eye candy, music, etc. Many thanks Fred, this would not have been possible without your ninja programming skills!!

I noticed that if I have a 64x64 map (the bottom 32 rows use the shared sprite/map area), Pico-8 seems to slow down when I draw the map with the shared area visible. I even tried to draw a constant 16x16 tile area (instead of drawing the full map and let clipping handle the rest as usual).
So my question is that is it really a feature that accessing the shared data is slower and if so, why doesn't that affect whatever number stat(1) returns?
Pico lacks native stack and queue support. I'm unhappy about it, so i cried a bit and my friend GreyKnight came up with a small implementation of a deque (queue/stack combo). From preliminary tests it works fine.
-- 3 tokens
push=add
-- 19 tokens
function pop(stack)
local v = stack[#stack]
stack[#stack]=nil
return v
end
-- 11 tokens
function pop_discard(stack)
stack[#stack]=nil
end
-- 3 tokens
enqueue=add
-- 16 tokens
function dequeue(queue)
local v = queue[1]
del(queue, v)
return v
end
----- Usage -----
stack = {}
push(stack, "goat")
push(stack, "billy")
assert("billy" == pop(stack))
assert("goat" == pop(stack))
queue = {}
enqueue(queue, "nanny")
enqueue(queue, "kid")
assert("nanny" == dequeue(queue))
assert("kid" == dequeue(queue))
|

[sorry if you have seen this already. I have no idea which posts show up where in this bbs and I keep on putting it in the wrong places]
I'm kind of working on a couple of shameful hacks for Pico.
The first one is a network stack. Since Hey @ lexaloffe is not answering my emails, I'm just keeping myself busy this way :p. I have a few ways I can try, including saving and reading from a cartridge that, in fact, is a named pipe. More on that later.
The second hack is an on-screen keypad. Android users can't use pico as the keyboard does not pop up. So I made a thingie. This is what it looks like on my desktop while I play PICO-2048:
So save this bookmarklet and use it in a cartridge page: [PICOPAD](javascript:(function()%7Bfunction%20insertAfter(referenceNode%2C%20newNode)%20%7BreferenceNode.parentNode.insertBefore(newNode%2C%20referenceNode.nextSibling)%3B%7Dfunction%20lp_key_event(letter%2C%20code%2C%20type)%7Bvar%20e%20%3D%20new%20Event(type)%3Be.key%3Dletter%3Be.keyCode%3Dcode%3Be.which%3De.keyCode%3Be.altKey%3Dfalse%3Be.ctrlKey%3Dtrue%3Be.shiftKey%3Dfalse%3Be.metaKey%3Dfalse%3Be.bubbles%3Dtrue%3Breturn%20e%3B%7Dwindow.pressZ%20%3D%20function()%7B%20%20%20%20%20%20document.dispatchEvent(lp_key_event(%22Z%22%2C%22Z%22.charCodeAt(0)%2C%22keydown%22))%3B%20%7D%3Bwindow.pressX%3D%20function()%7B%20%20%20%20%20%20document.dispatchEvent(lp_key_event(%22X%22%2C%22X%22.charCodeAt(0)%2C%22keydown%22))%3B%20%7D%3Bwindow.pressLeft%3D%20function()%7B%20%20%20document.dispatchEvent(lp_key_event(%22%22%2C37%2C%22keydown%22))%3B%20%7D%3Bwindow.pressUp%3D%20function()%7B%20%20%20%20%20document.dispatchEvent(lp_key_event(%22%22%2C38%2C%22keydown%22))%3B%20%7D%3Bwindow.pressRight%3D%20function()%7B%20%20document.dispatchEvent(lp_key_event(%22%22%2C39%2C%22keydown%22))%3B%20%7D%3Bwindow.pressDown%3D%20function()%7B%20%20%20document.dispatchEvent(lp_key_event(%22%22%2C40%2C%22keydown%22))%3B%20%7D%3Bwindow.releaseZ%3D%20function()%7B%20%20%20%20%20%20document.dispatchEvent(lp_key_event(%22Z%22%2C%22Z%22.charCodeAt(0)%2C%22keyup%22))%3B%20%7D%3Bwindow.releaseX%3D%20function()%7B%20%20%20%20%20%20document.dispatchEvent(lp_key_event(%22X%22%2C%22X%22.charCodeAt(0)%2C%22keyup%22))%3B%20%7D%3Bwindow.releaseLeft%3D%20function()%7B%20%20%20document.dispatchEvent(lp_key_event(%22%22%2C37%2C%22keyup%22))%3B%20%7D%3Bwindow.releaseUp%3D%20function()%7B%20%20%20%20%20document.dispatchEvent(lp_key_event(%22%22%2C38%2C%22keyup%22))%3B%20%7D%3Bwindow.releaseRight%3D%20function()%7B%20%20document.dispatchEvent(lp_key_event(%22%22%2C39%2C%22keyup%22))%3B%20%7D%3Bwindow.releaseDown%3D%20function()%7B%20%20%20document.dispatchEvent(lp_key_event(%22%22%2C40%2C%22keyup%22))%3B%20%7D%3Bvar%20el%20%3D%20document.createElement(%22div%22)%3Bel.innerHTML%20%3D%20%22%3Cdiv%3E%22%2B%22%3Cdiv%20style%3D%5C%22display%3Ainline-block%3B%5C%22%3E%22%2B%22%3Cdiv%20style%3D%5C%22width%3A100px%3B%20height%3A100px%3B%20%5C%22%3E%26nbsp%3B%3C%2Fdiv%3E%22%2B%22%3Cdiv%20style%3D%5C%22width%3A100px%3B%20height%3A100px%3B%20background%3Ared%3B%5C%22%20onMouseDown%3D%5C%22window.pressLeft()%5C%22%20onMouseUp%3D%5C%22window.releaseLeft()%5C%22%20ontouchstart%3D%5C%22window.pressLeft()%5C%22%20ontouchend%3D%5C%22window.releaseLeft()%5C%22%3E%20%26nbsp%3B%3C%2Fdiv%3E%22%2B%22%3Cdiv%20style%3D%5C%22width%3A100px%3B%20height%3A100px%3B%20%5C%22%3E%26nbsp%3B%3C%2Fdiv%3E%22%2B%22%3C%2Fdiv%3E%22%2B%22%3Cdiv%20style%3D%5C%22display%3Ainline-block%3B%5C%22%3E%22%2B%22%3Cdiv%20style%3D%5C%22width%3A100px%3B%20height%3A100px%3B%20background%3Agreen%3B%5C%22%20onMouseDown%3D%5C%22window.pressUp()%5C%22%20onMouseUp%3D%5C%22window.releaseUp()%5C%22%20ontouchstart%3D%5C%22window.pressUp()%5C%22%20ontouchend%3D%5C%22window.releaseUp()%5C%22%3E%26nbsp%3B%3C%2Fdiv%3E%22%2B%22%3Cdiv%20style%3D%5C%22width%3A100px%3B%20height%3A100px%3B%20%5C%22%3E%26nbsp%3B%3C%2Fdiv%3E%22%2B%22%3Cdiv%20style%3D%5C%22width%3A100px%3B%20height%3A100px%3B%20background%3Ablue%3B%5C%22%20onMouseDown%3D%5C%22window.pressDown()%5C%22%20onMouseUp%3D%5C%22window.releaseDown()%5C%22%20ontouchstart%3D%5C%22window.pressDown()%5C%22%20ontouchend%3D%5C%22window.releaseDown()%5C%22%3E%20%26nbsp%3B%3C%2Fdiv%3E%22%2B%22%3C%2Fdiv%3E%22%2B%22%3Cdiv%20style%3D%5C%22display%3Ainline-block%3B%5C%22%3E%22%2B%22%3Cdiv%20style%3D%5C%22width%3A100px%3B%20height%3A100px%3B%20%5C%22%3E%26nbsp%3B%3C%2Fdiv%3E%22%2B%22%3Cdiv%20style%3D%5C%22width%3A100px%3B%20height%3A100px%3B%20background%3Ared%3B%5C%22%20onMouseDown%3D%5C%22window.pressRight()%5C%22%20onMouseUp%3D%5C%22window.releaseRight()%5C%22%20ontouchstart%3D%5C%22window.pressRight()%5C%22%20ontouchend%3D%5C%22window.releaseRight()%5C%22%3E%20%26nbsp%3B%3C%2Fdiv%3E%22%2B%22%3Cdiv%20style%3D%5C%22width%3A100px%3B%20height%3A100px%3B%20%5C%22%3E%26nbsp%3B%3C%2Fdiv%3E%22%2B%22%3C%2Fdiv%3E%22%2B%22%3Cdiv%20style%3D%5C%22display%3Ainline-block%3B%5C%22%3E%22%2B%22%3Cdiv%20style%3D%5C%22width%3A100px%3B%20height%3A100px%3B%20%5C%22%3E%26nbsp%3B%3C%2Fdiv%3E%22%2B%22%3C%2Fdiv%3E%22%2B%22%3Cdiv%20style%3D%5C%22display%3Ainline-block%3B%5C%22%3E%22%2B%22%3Cdiv%20style%3D%5C%22width%3A100px%3B%20height%3A100px%3B%20%5C%22%3E%26nbsp%3B%3C%2Fdiv%3E%22%2B%22%3Cdiv%20style%3D%5C%22width%3A100px%3B%20height%3A100px%3B%20background%3Ared%3B%5C%22%20onMouseDown%3D%5C%22window.pressZ()%5C%22%20onMouseUp%3D%5C%22window.releaseZ()%5C%22%20ontouchstart%3D%5C%22window.pressZ()%5C%22%20ontouchend%3D%5C%22window.releaseZ()%5C%22%3E%26nbsp%3B%3C%2Fdiv%3E%22%2B%22%3Cdiv%20style%3D%5C%22width%3A100px%3B%20height%3A100px%3B%20%5C%22%3E%26nbsp%3B%3C%2Fdiv%3E%22%2B%22%3C%2Fdiv%3E%22%2B%22%3Cdiv%20style%3D%5C%22display%3Ainline-block%3B%5C%22%3E%22%2B%22%3Cdiv%20style%3D%5C%22width%3A100px%3B%20height%3A100px%3B%20%5C%22%3E%26nbsp%3B%3C%2Fdiv%3E%22%2B%22%3Cdiv%20style%3D%5C%22width%3A100px%3B%20height%3A100px%3B%20background%3Ablue%3B%5C%22%20onMouseDown%3D%5C%22window.pressX()%5C%22%20onMouseUp%3D%5C%22window.releaseX()%5C%22%20ontouchstart%3D%5C%22window.pressX()%5C%22%20ontouchend%3D%5C%22window.releaseX()%5C%22%3E%26nbsp%3B%3C%2Fdiv%3E%22%2B%22%3Cdiv%20style%3D%5C%22width%3A100px%3B%20height%3A100px%3B%20%5C%22%3E%26nbsp%3B%3C%2Fdiv%3E%22%2B%22%3C%2Fdiv%3E%22%3BinsertAfter(document.getElementById(%22canvas%22)%20%7C%7C%20document.getElementById(%22playarea_0%22)%2C%20el)%7D)())







1 comment


