Log In  


Cart #20212 | 2016-05-06 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA

I just started playing around with Pico-8 and while I've been programming for a very long time, I've never done so at such a low level so I'm finding P8 a great challenge that is wonderful escape from my daily style. That being said, I'm looking for code review-style feedback on my first little learning game.

I'm making a simple game for my preschooler daughter so it's not complicate but it's requiring me to cover all the basics for making any game - collisions, maps, sprites, movement, etc. This first pass focuses on movement and object/sprite collision. I watched the "popular" light cycle tutorial as well as read through the Fanzines and took all that cobble something together. So thanks to all of those people! It's be a treat learning something new.

Right now the game is just moving the character around and collecting food items. Run into a present and food pops out. Run into the food and they disappear (collected). That's it.

Again, I'm just looking for feedback on how it's written, probably mostly around the architecture and places where I'm wasting space. The game is working as I expected, so there are no bugs, per se...just looking for efficiencies.

I am planning on adding more graphics and stats that keep track of what's been collected. There will be other screens but that's the next lesson.

I appreciate any feedback, thanks!

pickups={}
player={}
box={}

-- ///////////////////////

function _init()
	cls()
	createplayer()
	createbox()
end

function _update()
	foreach(pickups,function(o)
		if (o.wild and collide(o,player)) then o.wild=false end
	end)

	if (collide(box,player) and box.closed) then
		box.closed=false
		for x=1,4 do add(pickups, createpickup()) end
		createbox()
	end

	player.update()

	if (btnp(5)) then createbox() end
end

function _draw()
	cls()
    foreach(pickups, function(o) o.draw()  end)

    player.draw()
    box.draw()
end

-- ///////////////////////

function createbox()
    box.closed=true
    box.x=flr(rnd(110)+10)
    box.y=flr(rnd(110)+10)
    box.hitbox={x=0, y=0, w=8, h=8}

    box.draw = function()
       if(box.closed) then spr(1,box.x,box.y) end
    end
end

function createplayer()
    player.x=60
    player.y=60
    player.spr={3,2}
    player.cel=2
	player.dir=1
    player.hitbox={x=1, y=0, w=6, h=8}

    player.update=function()
        -- movement controls
		if (btn(0)) then move(player,4) end
		if (btn(1)) then move(player,2) end
		if (btn(2)) then move(player,1) end
		if (btn(3)) then move(player,3) end		
    end

    player.draw=function()

        spr(player.spr[player.cel],player.x,player.y)
    end
end

function move(obj, dir)

obj.dir = dir
	if (obj.dir == 1) then obj.y = obj.y-1 end
	if (obj.dir == 2) then 
		obj.x = obj.x+1 
		player.flip = false
	end
	if (obj.dir == 3) then obj.y = obj.y+1 end
	if (obj.dir == 4) then 
		obj.x = obj.x-1 
		player.flip = true
	end

	if (obj.x <= 1) then obj.x = 1 end
	if (obj.y <= 3) then obj.y = 3 end
	if (obj.y >= (125-8)) then obj.y = (125-8) end
	if (obj.x >= (125-6)) then obj.x = (125-6) end

	--p.spr = p.spr + 1
	--if (p.spr > 2) then p.spr = 1 end
	if player.cel==1 then player.cel=2 else player.cel=1 end

end

createpickup=function()
    local obj={}
    obj.x=flr(rnd(110)+10)
    obj.y=flr(rnd(110)+10)
    obj.spr=flr(rnd(5)) + 64
    obj.hitbox={x=0, y=0, w=8, h=8}
    obj.wild=true

    obj.draw=function()
        if (obj.wild) then spr(obj.spr, obj.x, obj.y) end  
    end

    return obj
end

function collide(obj, other)
    if
        other.x+other.hitbox.x+other.hitbox.w > obj.x+obj.hitbox.x and 
        other.y+other.hitbox.y+other.hitbox.h > obj.y+obj.hitbox.y and
        other.x+other.hitbox.x < obj.x+obj.hitbox.x+obj.hitbox.w and
        other.y+other.hitbox.y < obj.y+obj.hitbox.y+obj.hitbox.h 
    then
        return true
    end
end


I think lua is prety open in term of style, specialy for Pico 8 where project's keep a small size. It's true that using same functions and variables in a coherent way can lead to smaller and clearer code. Your code seem prety good already.
I have two suggestions, first removing special code in the _update() function, and only calling each pickup/player update function. So collision test should be either in player or pickup update function.
The other thing is that I prefer to use a dirx/diry than a single dir. You can even call it velocityx/velocityy, store it in the player and have simple physics, acceleration and drag on you character.


It's great that you're making this for your child. :-) What would the code look like if, instead of spawning more objects, there was just one object on the screen that disappears when you collide with it? I'm still learning the basics, and this is the closest I have come to finding a simple pickup "tutorial".


Wow...an oldie but a goldie :) Glad you're able to use it to learn something. Doing little carts like this was exactly how I got started...just basic "how do I pick stuff up" game.

The code you're after is inside the _update() function. It's the if() condition that happens when the character collides with the present item. The 'for' loop inside that condition says "create 4 new pickups and a present".

So whatever you want to have happen when you hit the box, just put inside that if() condition. If you don't want more pickup items, just delete that 'for' line and the createbox() after it.

-- When player collides with a present, do something
if (collide(box,player) and box.closed) then
    ...do whatever you want...
end

Hope that helps a bit. The collide() function is the magic that detects when things run into each other. Honestly, that bit of code is somewhat inefficient as you see it there, but it does work just fine.

And if you're interested, that code above turned into this game...it's a little more game-y and one my kid actually played a few times.
https://www.lexaloffle.com/bbs/?pid=20318&tid=3310


Here's a link to a Pico-8 boilerplate I used when starting a new game.

https://github.com/morningtoast/pico8dev/blob/master/boilerplate.p8

The most useful stuff for you is probably at the bottom of the code, just search for #utility and you'll see a bunch of helper functions that do things like collision, angles, distance and some text functions.

The boilerplate as a whole is a little out of date from what I use today (I need to update it) but it's plenty good to try out for learning.



[Please log in to post a comment]