PICO-8 Character Tester https://www.lexaloffle.com/bbs/?tid=34266
-- character tester | |
-- by grotandthemob | |
local game_objects | |
function _init() | |
-- create game objects | |
game_objects={} | |
-- particles | |
part={} | |
-- create player object | |
make_player(56,104) | |
for i=1,16 do | |
make_block(8*i-8,128) | |
end | |
end | |
function _update() | |
local obj | |
-- update all the game objects | |
for obj in all(game_objects) do | |
obj:update() | |
end | |
end | |
function _draw() | |
-- clear the screen | |
cls(1) | |
-- draw the game ovjects | |
local obj | |
for obj in all(game_objects) do | |
obj:draw() | |
end | |
-- write stuff | |
print("character test room", 8, 8, 13) | |
print("move:\x8b \x91 fart:\x83", 8, 16, 13) | |
print("jump:\x97/\x94 accelerate:\x8e", 8, 24, 13) | |
end | |
-- game object creation functions | |
function make_player(x,y) | |
return make_game_object("player",x,y,{ | |
width=8, | |
height=8, | |
move_speed=0.8, | |
is_standing_on_block=false, | |
is_facing_left=false, | |
was_landed=false, | |
walk_counter=0, | |
velocity_y=-4, | |
landing_counter=0, | |
old_move_speed=move_speed, | |
update=function(self) | |
updateparts(self.is_facing_left) | |
-- update walk counter | |
if self.walk_counter==0 then | |
self.walk_counter=8 | |
else | |
self.walk_counter-=0.5 | |
end | |
if self.landing_counter == 0 then | |
self.landing_counter = 0 | |
else | |
self.landing_counter-=1 | |
end | |
self.velocity_x*=0.5 | |
-- self.velocity_y*=0.95 | |
-- RIGHT -> | |
if btn(1) then | |
self.is_facing_left=false | |
if self.velocity_x and btn(4) then | |
-- dusttrail(self.x,self.y) | |
spawntrail(self.x,self.y) | |
self.velocity_x+=self.move_speed*2 | |
else | |
self.velocity_x+=self.move_speed | |
end | |
end | |
-- LEFT <- | |
if btn(0) then | |
self.is_facing_left=true | |
if self.velocity_x and btn(4) then | |
-- dusttrail(self.x,self.y) | |
spawntrail(self.x,self.y) | |
self.velocity_x-=self.move_speed*2 | |
else | |
self.velocity_x-=self.move_speed | |
end | |
end | |
-- UP ��� | |
if (btn(2) or btn(5)) and self.is_standing_on_block then | |
self.is_standing_on_block=false | |
self.was_landed=false | |
if btn(4) then | |
self.velocity_y=-self.move_speed*4 | |
for i=1,4 do | |
dusttrail(self.x,self.y) | |
end | |
else | |
self.velocity_y=-self.move_speed*2 | |
for i=1,2 do | |
dusttrail(self.x,self.y) | |
end | |
end | |
end | |
-- DOWN ��� | |
if btn(3) then | |
self.landing_counter=4 | |
for i=1,2 do | |
dusttrail(self.x,self.y) | |
end | |
end | |
-- apply gravity | |
self.velocity_y+=0.3 | |
-- make sure velocity not gets too big | |
self.velocity_y=mid(-6,self.velocity_y,3) | |
self.x+=self.velocity_x | |
self.y+=self.velocity_y | |
-- limit the player to stay visible | |
if self.x > 115 then | |
self.x = 115 | |
end | |
if self.y < 12 then | |
self.y = 12 | |
end | |
if self.x < -3 then | |
self.x = -3 | |
end | |
if self.y > 128 then | |
self.y = 128 | |
end | |
-- check to see if colliding with coin | |
for_each_game_object("coin", function(coin) | |
if self:check_for_hit(coin) and not coin.is_collected then | |
coin.is_collected=true | |
-- sfx(1) | |
end | |
end) | |
-- check to see if colliding with block | |
for_each_game_object("block", function(block) | |
if self:check_for_hit(block) then | |
-- score=0 | |
-- sfx(2) | |
end | |
end) | |
-- check to see if colliding with blocks | |
local was_standing_on_block=self.is_standing_on_block | |
self.is_standing_on_block=false | |
for_each_game_object("block", function(block) | |
local collision_dir=self:check_for_collision(block,3.1) | |
self:handle_collision(block,collision_dir) | |
if collision_dir=="down" then | |
self.is_standing_on_block=true | |
if not was_standing_on_block then | |
-- sfx(2) | |
self.was_landed=true | |
self.landing_counter = 4 | |
for i=1,8 do | |
dusttrail(self.x,self.y) | |
end | |
end | |
end | |
end) | |
end, | |
draw=function(self) | |
-- self:draw_bounding_box(7) | |
local sprite_num | |
if self.is_standing_on_block then | |
if self.velocity_x==mid(-0.1,self.velocity_x,0.1) and self.landing_counter==0 then | |
sprite_num=16 | |
elseif self.walk_counter<4 then | |
sprite_num=24 | |
else | |
sprite_num=24 | |
end | |
else | |
if self.velocity_y>0 then | |
sprite_num=20 | |
else | |
if self.velocity_x < 0.2 and self.velocity_x > -0.2 then | |
sprite_num=18 | |
else | |
sprite_num=26 | |
end | |
end | |
end | |
-- particles | |
drawparts() | |
-- sprites | |
spr(sprite_num, self.x,self.y-8,2,2,self.is_facing_left) | |
-- print(self.landing_counter,0,0,7) | |
end, | |
check_for_block_collision=function(self,block) | |
end | |
}) | |
end | |
function make_block(x,y) | |
return make_game_object("block",x,y,{ | |
width=8, | |
height=8, | |
draw=function(self) | |
spr(3,self.x,self.y) | |
-- rect(self.x,self.y,self.x+self.width,self.y+self.height,8) | |
end | |
}) | |
end | |
function make_game_object(name,x,y,props) | |
local obj={ | |
name=name, | |
x=x, | |
y=y, | |
velocity_x=0, | |
velocity_y=0, | |
update=function(self) | |
-- do nothing | |
end, | |
draw=function(self) | |
-- don't draw anything | |
end, | |
draw_bounding_box=function(self,color) | |
rect(self.x,self.y,self.x+self.width,self.y+self.height,color) | |
end, | |
center=function(self) | |
return self.x+self.width/2, self.y+self.height/2 | |
end, | |
check_for_hit=function(self,other) | |
return bounding_boxes_overlaping(self,other) | |
end, | |
check_for_collision=function(self,other,indent) | |
--calculate the four hitboxes | |
local x,y,w,h = self.x,self.y,self.width,self.height | |
local top_hitbox={x=x+indent,y=y,width=w-2*indent,height=h/2} | |
local bottom_hitbox={x=x+indent,y=y+h/2,width=w-4,height=h/2} | |
local left_hitbox={x=x,y=y+indent,width=w/2,height=h-2*indent} | |
local right_hitbox={x=x+w/2,y=y+indent,width=w/2,height=h-2*indent} | |
if bounding_boxes_overlaping(bottom_hitbox,other) then | |
return "down" | |
elseif bounding_boxes_overlaping(left_hitbox,other) then | |
return "left" | |
elseif bounding_boxes_overlaping(right_hitbox,other) then | |
return "right" | |
elseif bounding_boxes_overlaping(top_hitbox,other) then | |
return "up" | |
end | |
end, | |
handle_collision=function(self,other,dir) | |
if dir=="down" then | |
self.y=other.y-self.height | |
if self.velocity_y>0 then | |
self.velocity_y=0 | |
end | |
elseif dir=="left" then | |
self.x=other.x+other.width | |
if self.velocity_x<0 then | |
self.velocity_x=0 | |
end | |
elseif dir=="right" then | |
self.x=other.x-self.width | |
if self.velocity_x>0 then | |
self.velocity_x=0 | |
end | |
elseif dir=="up" then | |
self.y=other.y+other.height | |
if self.velocity_y<0 then | |
self.velocity_y=0 | |
end | |
end | |
end | |
} | |
-- add additional properties | |
local key,value | |
for key,value in pairs(props) do | |
obj[key]=value | |
end | |
-- add it to the list of game objects | |
add(game_objects,obj) | |
-- return game object | |
return obj | |
end | |
-- hit detection | |
function lines_overlapping(min1,max1,min2,max2) | |
return max1>min2 and max2>min1 | |
end | |
function rects_overlapping(left1,top1,right1,bottom1,left2,top2,right2,bottom2) | |
return lines_overlapping(left1,right1,left2,right2) and lines_overlapping(top1,bottom1,top2,bottom2) | |
end | |
function bounding_boxes_overlaping(obj1,obj2) | |
return rects_overlapping(obj1.x,obj1.y,obj1.x+obj1.width,obj1.y+obj1.height,obj2.x,obj2.y,obj2.x+obj2.width,obj2.y+obj2.height) | |
end | |
-- game object helper functions | |
function for_each_game_object(name,callback) | |
local obj | |
for obj in all(game_objects) do | |
if obj.name==name then | |
callback(obj) | |
end | |
end | |
end | |
-- particles | |
-- add a particle | |
function addpart(_x,_y,_type,_maxage,_col,_oldcol,_xspeed,_yspeed,_initialr) | |
local _p = {} | |
_p.x=_x | |
_p.y=_y | |
_p.tpe=_type | |
_p.mage=_maxage | |
_p.age=0 | |
_p.col=_col | |
_p.oldcol=_oldcol | |
_p.xspeed=_xspeed | |
_p.yspeed=_yspeed | |
_p.r=_initialr | |
add(part,_p) | |
end | |
-- spawn a trail particle | |
function spawntrail(_x,_y) | |
if rnd()<1 then | |
local _radius = 3 | |
local _ang = rnd() | |
local _dx = sin(_ang)*_radius | |
local _dy = cos(_ang)*_radius | |
addpart(_x+_dx,_y+_dy,0,10+rnd(5),10,9,0.6,-0.1,2) | |
end | |
end | |
function dusttrail(_x,_y) | |
if rnd()<1 then | |
local _radius = 8 | |
-- local _ang = rnd() | |
-- local _dx = sin(_ang)*_radius | |
-- local _dy = cos(_ang)*_radius | |
local _ang = rnd() | |
local _dx = rnd()*24 | |
local _dy = 4 | |
addpart(_x+_dx-12,_y+_dy,0,20+rnd(5),6,13,0,-(rnd()/2),4) | |
end | |
end | |
function updateparts(is_facing_left) | |
local _p | |
for i=#part,1,-1 do | |
_p=part[i] | |
_p.age+=1 | |
_p.r-=0.2 | |
if is_facing_left then | |
_p.x+=_p.xspeed | |
else | |
_p.x-=_p.xspeed | |
end | |
_p.y+=_p.yspeed | |
if _p.age > _p.mage then | |
del(part,part[i]) | |
else | |
if (_p.age / _p.mage) > 0.5 then | |
_p.col = _p.oldcol | |
end | |
end | |
end | |
end | |
function drawparts() | |
for i=1,#part do | |
_p=part[i] | |
-- pixel particle | |
if _p.tpe == 0 then | |
pset(_p.x+8,_p.y+4,_p.col) | |
circfill(_p.x+8, _p.y+4, _p.r, _p.col) | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment