Created
October 27, 2019 14:44
-
-
Save tomfejer/e50762979fe10da42e5b9c0b9a1fa314 to your computer and use it in GitHub Desktop.
PICO-8 Character Tester https://www.lexaloffle.com/bbs/?tid=34266
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- 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