| | |
ThatFallingBlockGame was a Tetris clone created on the User Generated Content platform Metaplace.com. With the closing of that platform, the game can no longer be played, so all that remains is a short sample of video and the scripts used to create the game, which are posted below.
The not-necessarily-pretty-but-functional scripts include:
- player - to manage input from the client
- world - for storing scores and exposing those score via web servies
- tet_grid - manages the play area and checks for line completion
- block_spawner - spawns blocks!
- master_block - invisible object that represents the Tetromino and is a
- control object for the individual blocks.
- block - the individual blocks of a Tetromino.
- tfbg.php - an external php file that connected to the game world to extract and render highscores as a png to be displayed on the games profile page.
(Note: the following uses a very simple and quickly hacked syntax highlighting, so there may be errors...)
The player script: as can be seen this script started off as a default player script, so there is some old code remaining that was never removed.
Code: MetaScript
-- PLAYER default player with 4-way sliding movement.
-- Basic four directional movement for top-down view using SlideObject.
-- Usage: Attach this behavior to individual player objects to provide a basic top down movement via sliding based on move_speed.
--
-- Created by: Thor Alexander
-- Created on: 11/28/2007
-- Version 1.1
--
-- Version History:
-- 1.1 11/28 Initial release. (TA)
-- 1.2 2/28/08 Update for self changes. (JW)
--- constants
--- properties
Define Properties()
-- Parameters
spawner = '_object_'
move_speed = 1.0
ExposeProperty( 'move_speed', 'Movement rate in tiles/second.')
SetPropRange( 'move_speed', 0, 10 )
pause = 0
ui = {}
continous_move = 0
continous_moves = 0
continous_move_down = 0
meeper = 1
end
GAME_OVER = '0:26'
PLAY_AGAIN1 = '0:27'
PLAY_AGAIN2 = '0:28'
PLAY1 = '0:29'
PLAY2 = '0:31'
NAME = '0:30'
CONTROLS = '0:32'
PAUSED = '0:39'
CONTINOUS_MOVE_INTERVAL = 100
--- commands
Define Commands()
MakeInput("Press 'LEFT' to start moving left.", 'left', 'down', 'none', 'move_block left')
MakeInput("Press 'RIGHT' to start moving left.", 'right', 'down', 'none', 'move_block right')
MakeInput("Press 'UP' to start moving up.", 'up', 'down', 'none', 'move_block up')
MakeInput("Press 'DOWN' to start moving up.", 'down', 'down', 'none', 'move_block down')
MakeInput("Release 'LEFT' to stop moving left.", 'left', 'up', 'none', 'move_block stop')
MakeInput("Release 'RIGHT' to stop moving left.", 'right', 'up', 'none', 'move_block stop')
MakeInput("Release 'DOWN' to stop moving up.", 'down', 'up', 'none', 'move_block stop')
MakeInput('hold','space','down','none','hold')
MakeInput('clockwise','z','down','none','rotate_block clock')
MakeInput('anti-clockwise','x','down','none','rotate_block anti')
MakeInput('pause','p','down','none','pause')
MakeInput('scoreboard','h','down','none','scoreboard 604800')
MakeInput('controls','c','down','none','controls')
MakeInput('meeper','m','down','none','meeper')
MakeCommand('move_block', 'Move', 'dir:string')
MakeCommand('meeper','meeper')
MakeCommand('rotate_block','rotate_block','dir:string')
MakeCommand('clear', 'clear')
MakeCommand('hold','hold')
MakeCommand('pause','pause')
MakeCommand('new_game','new_game')
MakeCommand('scoreboard','scoreboard','interval:int', 'pos:int', 'force:int')
MakeCommand('controls','controls')
MakeCommand('goto_central','goto_central')
end
Command goto_central()
UserGotoWorld(self,'mpcentrallive')
end
Command meeper()
if self.meeper == 0 then
self.meeper = 1
else
self.meeper = 0
end
end
Command controls()
SendTo(self,'display_controls',0)
end
Command scoreboard(interval, pos, force)
SendTo(self,'display_hiscore',0, pos,15,nil,0,interval,force)
-- (pos, num, status, off, interval)
end
Command new_game()
self.pause = 0
--(pos, num, status, off, interval,force)
SendTo(self,'display_hiscore',0,nil,nil,nil,1)
SendTo(self,'display_controls',0,nil,1)
SendTo(self.spawner.grid,'init',0)
SendTo(self.spawner,'start_game',50)
end
Command pause()
if self.spawner.grid.game_status == 1 then
if self.pause == 0 then
self.ui['pause_bg'] = UiRect(0, 'pause', 0, 0, 640, 480)
UiColor(self.ui.pause_bg, 0,0,0,0.5)
UiAlign(self.ui.pause_bg, 0, 0, 'top_left', 'scale_both')
UiAttachUser(self, self.ui.pause_bg)
self.ui['pause_img'] = UiImage(0,'pause_img',0,0,200,50,PAUSED)
UiAlign(self.ui.pause_img, 0, 0, 'center', 'scale_none')
UiAttachUser(self, self.ui.pause_img)
UiVisible(self.ui.pause_img, 1)
self.pause = 1
SendTo(self.spawner,'lock',0)
else
if self.ui.pause_img then UiDelete(self.ui.pause_img) self.ui.pause_img = nil end
if self.ui.pause_bg then UiDelete(self.ui.pause_bg) self.ui.pause_bg = nil end
self.pause = 0
SendTo(self.spawner,'unlock',0)
end
end
end
Command clear()
if IsSuperuser(self) == 1 then
local objs = FindObjectsInPlaceById(GetPlace(),'0:4')
for _,v in ipairs(objs) do
DestroyObject(v)
end
local objs = FindObjectsInPlaceById(GetPlace(),'0:5')
for _,v in ipairs(objs) do
DestroyObject(v)
end
end
end
Command rotate_block(dir)
if self.spawner.grid.game_status == 1 and self.pause == 0 then
if self.spawner then
SendTo(self.spawner,'rotate_block',0,dir)
end
end
end
Command hold()
if self.spawner.grid.game_status == 1 and self.pause == 0 then
if self.spawner then
SendTo(self.spawner,'hold',0)
end
end
end
Command move_block(dir)
if dir == 'stop' then
self.continous_move = 0
self.continous_moves = 0
self.continous_move_down = 0
else
self.continous_move = 1
SendTo(self,'continous_move',0,dir)
end
end
-- triggers
Trigger enter()
--MoveObject(self,0,0,0,1)
enter(self)
end
Trigger continous_move(dir)
if self.continous_move == 1 then
if self.spawner.grid.game_status == 1 and self.pause == 0 then
if self.spawner then
if dir == 'down' then self.continous_move_down = 1 end
SendTo(self.spawner,'move_block',0,dir)
if dir == 'down' then
local interval = CONTINOUS_MOVE_INTERVAL
if self.continous_moves == 0 then interval = CONTINOUS_MOVE_INTERVAL * 2 end
SendTo(self,'continous_move',interval,dir)
self.continous_moves = self.continous_moves + 1
end
end
end
end
end
Trigger display_hiscore(pos, num, status, off, interval,force)
local killed = false
if type(force) ~= 'number' then force = nil end
if self.ui.hi_score_bg or off == 1 then
if self.ui.hi_score_bg then
UiDelete(self.ui.hi_score_bg)
UiDelete(self.ui.hi_score_win)
self.ui.hi_score_win = nil
self.ui.hi_score_bg = nil
killed = true
end
end
if off ~= 1 and (force or not killed) then
self.ui['hi_score_bg'] = UiRect(0, 'hi_score', 0, 0, 640, 480)
UiColor(self.ui.hi_score_bg, 0,0,0,0.5)
UiAlign(self.ui.hi_score_bg, 0, 0, 'top_left', 'scale_both')
UiAttachUser(self, self.ui.hi_score_bg)
self.ui['hi_score_win'] = hi_score(self, 0, pos, num, 0, 0, status,interval)
UiAlign(self.ui.hi_score_win, 0, 0, 'center', 'scale_none')
UiAttachUser(self, self.ui.hi_score_win)
UiVisible(self.ui.hi_score_win, 1)
end
end
Trigger display_controls(status, off)
if self.ui.controls_bg or off == 1 then
if self.ui.controls_bg then
UiDelete(self.ui.controls_bg)
UiDelete(self.ui.controls_win)
self.ui.controls_win = nil
self.ui.controls_bg = nil
end
else
self.ui['controls_bg'] = UiRect(0, 'controls', 0, 0, 640, 480)
UiColor(self.ui.controls_bg, 0,0,0,0.5)
UiAlign(self.ui.controls_bg, 0, 0, 'top_left', 'scale_both')
UiAttachUser(self, self.ui.controls_bg)
self.ui['controls_win'] = controls(self, 0, 0, 0, status)
UiAlign(self.ui.controls_win, 0, 0, 'center', 'scale_none')
UiAttachUser(self, self.ui.controls_win)
UiVisible(self.ui.controls_win, 1)
end
end
--functions
function hi_score(self, parent, pos, num, dx, dy, status, interval)
interval = tonumber(interval) or 0
if type(pos) ~= 'number' or (type(pos) == 'number' and pos <1 ) then pos = 0 end
if type(num) ~= 'number' then num = 15 end
local height = (20*num)+120
if pos and pos > num then
height = (20*(num+1))+120
end
local hi_score_win = UiWindow(parent, 'hi_score_win', dx, dy, 300, height, '0:7')
if status == 1 or self.spawner.grid.game_status == 0 then
local img = UiImage(hi_score_win, 'game_over', 50,5, 199,37,GAME_OVER)
UiImageButton(hi_score_win,'play_again', 50,height-45,200,40,PLAY_AGAIN1,PLAY_AGAIN2,PLAY_AGAIN2,'new_game')
end
local TW_text
local AT_text
if interval > 0 then
TW_text = "<b>THIS WEEK</b>"
AT_text = "All Time"
else
TW_text = "This Week"
AT_text = "<b>ALL TIME</b>"
end
local this_week = UiTextButton(hi_score_win,'this_week',20,45,100,25,'0:7',TW_text,'scoreboard 604800 '..pos..' 1')
local all_time = UiTextButton(hi_score_win,'all_time',170,45,100,25,'0:7',AT_text,'scoreboard 0 '..pos..' 1')
UiVisible(hi_score_win, 0)
local w = GetWorld()
local tot = 0
local i = 1
local red = false
while tot<num do
local score = w.hi_score[i]
i = i + 1
if score then
local go = true
if interval > 0 and os.time() - tonumber(score.date) > interval then
go = false
end
if go then
tot = tot+1
local tot_off = 0
if tot >= 10 then
tot_off = -9
end
local l = UiMultiLabel(hi_score_win, 'score'..i, 35+tot_off, (tot*20)+50, 80, 25, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0)
local html = "<font size='14'>"
if pos == i-1 then
html = "<font size='14' color='#ff0000'>"
red = true
end
UiText(l, html..tot..") "..score.score.."</font>")
local lvl = UiMultiLabel(hi_score_win, 'score'..i, 115, (tot*20)+50, 120, 25, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0)
local level = score.level and score.level or '?'
UiText(lvl, html..level.."</font>")
local n = UiMultiLabel(hi_score_win, 'score'..i, 150, (tot*20)+50, 120, 25, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0)
UiText(n, html..score.username.."</font>")
end
else
break
end
end
if pos and pos > num and not red then
local score = w.hi_score[pos]
if score then
local l = UiMultiLabel(hi_score_win, 'score'..pos, 35-9, ((num+1)*20)+50, 80, 25, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0)
UiText(l, "<font size='14' color='#ff0000'>"..pos..") "..score.score.."</font>")
local n = UiMultiLabel(hi_score_win, 'score'..pos, 115, ((num+1)*20)+50, 120, 25, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0)
local level = score.level and score.level or '?'
UiText(n, "<font size='14' color='#ff0000'>"..level.."</font>")
local n = UiMultiLabel(hi_score_win, 'score'..pos, 150, ((num+1)*20)+50, 120, 25, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0)
UiText(n, "<font size='14' color='#ff0000'>"..score.username.."</font>")
end
end
return hi_score_win
end
function controls(self, parent, dx, dy, status)
local height = 390
local controls_win = UiWindow(parent, 'controls_win', dx, dy, 420, height, '0:7')
local img = UiImage(controls_win, 'name', 10,5, 400,80,NAME)
local con = UiImage(controls_win, 'con', 10,80, 400,270,CONTROLS)
if status == 1 or self.spawner.grid.game_status == 0 then
UiImageButton(controls_win,'play', 110,height-45,200,40,PLAY1,PLAY2,PLAY2,'new_game')
end
UiVisible(controls_win, 0)
return controls_win
end
Trigger ready_waiting()
if self.spawner then
SendTo(self,'display_controls',0,1)
end
end
function enter(self)
local grid = FindObjectsInPlaceById(GetPlace(),'0:7')[1]
if grid then
SendTo(grid,'join_game',0,self)
SendTo(self,'ready_waiting',0)
else
Debug('I cant find a grid')
end
end
world
Code: MetaScript
Define Properties()
fontrec = {sprite='24614:593', width=15,height=20 }
fontrec_lcd_blue = {sprite='24598:573', width=15,height=20 }
hi_score = {}
PersistProperty('hi_score')
end
WebTrigger scoreboard(request)
WebResponse(200)
WebHeader("content-type: text/html")
local num = 15
local interval = request.interval and tonumber(request.interval) or 0
local response = '<scores>'
local total = 0
local i = 1
while total<num do
local score = self.hi_score[i]
i = i + 1
if score then
local go = true
if interval > 0 and os.time() - tonumber(score.date) > interval then
go = false
end
if go then
total = total + 1
response = response .. '<score>'
response = response .. '<username>' .. score.username .. '</username>'
response = response .. '<user_score>' .. score.score .. '</user_score>'
local level = score.level ~= nil and score.level or ''
response = response .. '<level>' .. level .. '</level>'
response = response .. '<date>' .. score.date .. '</date>'
response = response .. '</score>'
end
else
break
end
end
response = response .. '</scores>'
WebWrite(response)
WebEnd()
end
WebTrigger scoreboard2(request)
WebResponse(200)
WebHeader("content-type: text/html")
local num = 15
local response = '<scores>'
for i=1,num do
local score = self.hi_score[i]
if score then
response = response .. '<score>'
response = response .. '<username>' .. score.username .. '</username>'
response = response .. '<user_score>' .. score.score .. '</user_score>'
local level = score.level ~= nil and score.level or ''
response = response .. '<level>' .. level .. '</level>'
response = response .. '<date>' .. score.date .. '</date>'
response = response .. '</score>'
else
break
end
end
response = response .. '</scores>'
WebWrite(response)
WebEnd()
end
Trigger add_score(user, score, level, status)
local pos = 0
if #self.hi_score > 0 then
for i,v in ipairs(self.hi_score) do
if score > v.score then
local tab = {}
tab.score = score
tab.username = user.name
tab.level = level
tab.date = os.time()
table.insert(self.hi_score, i, tab)
pos = i
break
end
end
end
if pos == 0 then
local tab = {}
tab.score = score
tab.username = user.name
tab.date = os.time()
if #self.hi_score > 0 then
pos = #self.hi_score + 1
else
pos = 1
end
table.insert(self.hi_score, pos, tab)
end
SendTo(user, 'display_hiscore', 0, pos, nil, status)
end
Trigger login(connectionId, userId, player)
SendTo(self, "goto_instance", 0, player, "0:0")
end
Trigger logout(connectionId, userId, player)
SendTo(self, "left_instance", 0, player)
end
tet_grid
Code: MetaScript
Define Properties()
t_grid_x1 = 1
ExposeProperty('t_grid_x1','x1')
-- PersistProperty('t_grid_x1')
t_grid_x2 = 10
ExposeProperty('t_grid_x2','x2')
-- PersistProperty('t_grid_x2')
t_grid_y1 = 2
ExposeProperty('t_grid_y1','y1')
-- PersistProperty('t_grid_y1')
t_grid_y2 = 22
ExposeProperty('t_grid_y2','y2')
-- PersistProperty('t_grid_y2')
eval_dir = 'y'
ExposeProperty('eval_dir','eval_dir')
PersistProperty('eval_dir')
no_spawners = 1
eval_buffer = {}
del_buffer = {}
spawners = {}
interval = 1000
game_status = 0
score = 0
level = 1
lines = 0
last_lines = 0
ui = {}
IncludeScript("21769:58")
end
LINE_SCORES = { [1] = 100, [2] = 300, [3] = 500, [4] = 800 }
GAME_STARTED = 1
SPAWNER_MAP = { [1] = { x = 0, y = 1 },
[2] = { x = 0, y = 2 },
[3] = { x = 1, y = 0 },
[4] = { x = 2, y = 0 }
}
LEVEL = {SPRITE='0:35',WIDTH=55,HEIGHT=18}
LINES = {SPRITE='0:34',WIDTH=70,HEIGHT=18}
SCORE = {SPRITE='0:38',WIDTH=72,HEIGHT=18}
HISCORE = {SPRITE='0:37',WIDTH=105,HEIGHT=18}
EXPLOSION = '19143:486'
--triggers
Trigger use(user)
--[[
SendTo(self,'init',0)
SendTo(self,'join_game',0,user)
for _,spawner in ipairs(self.spawners) do
if IsA(spawner, 'block_spawner') then
SendTo(spawner,'start_game',0)
end
end
--]]
end
Trigger attach()
self.spriteId = '-1:-1'
table.clear(self.spawners)
SendTo(self,'init',10)
end
Trigger init(user)
self.score = 0
self.lines = 0
self.level = 1
self.last_lines = 0
--clear blocks
local objs = FindObjectsInPlaceById(GetPlace(),'0:4')
for _,v in ipairs(objs) do
if v.grid == self then
DestroyObject(v)
end
end
local objs = FindObjectsInPlaceById(GetPlace(),'0:5')
for _,v in ipairs(objs) do
if v.spawner.grid == self then
DestroyObject(v)
end
end
build_ui(self, user)
for _,spawner in ipairs(self.spawners) do
if IsA(spawner, 'block_spawner') then
SendTo(spawner,'init',0)
end
end
end
Trigger join_game(user)
if self.game_status ~= GAME_STARTED then
--game hasn't started yet
if #self.spawners < self.no_spawners then
--we still have room
local spawned = false
for i,v in ipairs(self.spawners) do
if v.player == user then
spawned = true
break
end
end
--user not already joined
if not spawned then
add_spawner(self, user, 1)
end
end
end
end
Trigger eval_drop(coord,spawner)
local e = {}
local r_objs = {}
local axis = self.eval_dir == 'x' and 'y' or 'x'
local l = true
e['e_y'] = coord
if eval_dir == 'x' then e['e_x'] = coord end
for j=self['t_grid_'..axis..'1'],self['t_grid_'..axis..'2'] do
e['e_x'] = j
if eval_dir == 'x' then e['e_y'] = j end
local objs = GetObjectsAt(e.e_x, e.e_y)
if objs then
for _,obj in ipairs(objs) do
if obj.type == 'block' then
table.insert(r_objs, obj)
else
l = false
break
end
end
else
l = false
break
end
end
if l then
table.insert(self.eval_buffer, r_objs)
end
end
Trigger eval_clean(spawner)
local axis = self.eval_dir == 'x' and 'y' or 'x'
local lines = #self.eval_buffer
table.clear(self.del_buffer)
local l = 0
if lines > 0 then
for i=1,lines do
local r_objs = table.remove(self.eval_buffer)
--complete line
if #r_objs == self['t_grid_'..axis..'2'] - self['t_grid_'..axis..'1'] + 1 then
for _,o in ipairs(r_objs) do
l = o[self.eval_dir] > l and o[self.eval_dir] or l --might not be more than
TintSprite(o, 'none', 255,255,128)
if spawner.player.meeper == 1 then
o.spriteId = EXPLOSION
PlaySpriteAnim(o,1,12,0,'play_once',500)
end
--o.lifetime = 500
table.insert(self.del_buffer, o)
end
end
end
--lock spanwer
for _,s in ipairs(self.spawners) do
SendTo(s, 'lock', 0)
end
SendTo(self, 'del_clean', 500, l, spawner, lines)
end
end
Trigger del_clean(coord, spawner,li)
for _,v in ipairs(self.del_buffer) do
DestroyObject(v)
end
table.clear(self.del_buffer)
local axis = self.eval_dir == 'x' and 'y' or 'x'
local r = {}
local d = -1 --might not be
local lines = 1
for i=coord+d,self['t_grid_'..self.eval_dir..'1'],d do
r['e_y'] = i
local empty = true
if eval_dir == 'x' then r['e_x'] = coord end
for j=self['t_grid_'..axis..'1'],self['t_grid_'..axis..'2'] do
r['e_x'] = j
if eval_dir == 'x' then r['e_y'] = j end
local objs = GetObjectsAt(r.e_x, r.e_y)
if objs then
for _,obj in ipairs(objs) do
if obj.type == 'block' then
MoveObject(obj, obj.x+(lines*spawner.dx), obj.y+(lines*spawner.dy), obj.z, 1)
empty = false
end
end
end
end
if empty then
lines = lines + 1
end
end
if li > 0 then
local mod = ( self.last_lines == 4 and li == 4 ) and 1.5 or 1
self.last_lines = li
update_score(self, self.level*LINE_SCORES[li]*mod)
update_lines(self, li)
end
--unlock spawner
for _,s in ipairs(self.spawners) do
SendTo(s, 'unlock', 0)
end
end
Trigger update_score(score)
update_score(self,score)
end
Trigger game_over(spawner)
self.game_status = 0
SendTo(GetWorld(),'add_score',0,spawner.player,self.score,self.level,1)
end
--functions
function add_spawner(self, user, p)
if p <= self.no_spawners and self.spawners[p] == nil then
local x = SPAWNER_MAP[p].x ~= 0 and self['t_grid_x'..SPAWNER_MAP[p].x] or math.ceil((self.t_grid_x2 - self.t_grid_x1)/2)+1
local y = SPAWNER_MAP[p].y ~= 0 and self['t_grid_y'..SPAWNER_MAP[p].y]-1 or math.ceil((self.t_grid_y2 - self.t_grid_y1)/2)+1
local spawner = CreateObjectById('0:6', x, y, 1, 0 )
table.insert(self.spawners, spawner)
spawner.grid = self
if user then
SendTo(spawner,'init',0,user)
end
end
end
function update_score(self,score)
self.score = self.score + score
if self.ui.score then UiDelete(self.ui.score) end
self.ui['score'] = UiFontLabel(self.ui.score_bg,"score_text",10,10,tostring(self.score),GetWorld().fontrec_lcd_blue,nil,nil,1)
end
function update_lines(self,lines)
self.lines = self.lines + lines
if self.ui.lines then UiDelete(self.ui.lines) end
self.ui['lines'] = UiFontLabel(self.ui.lines_bg,"lines_text",10,10,tostring(self.lines),GetWorld().fontrec_lcd_blue,nil,nil,2)
if math.floor(self.lines/10) == self.level then
self.level = self.level + 1
if self.level == 5 then
local obj = GetObjectAt(-5,22)
if not obj then
CreateObjectById('59821:4',-5,22,0,0)
end
end
if self.ui.level then UiDelete(self.ui.level) end
self.ui['level'] = UiFontLabel(self.ui.level_bg,"level_text",10,10,tostring(self.level),GetWorld().fontrec_lcd_blue,nil,nil,2)
end
end
function build_ui(self,user)
local anchors = FindObjectsInPlaceById(GetPlace(), '0:8')
if anchors then
for _,anchor in ipairs(anchors) do
if anchor.anchor_name == 'score' then
self.ui['score_anchor'] = anchor
if self.ui.score_bg then UiDelete(self.ui.score_bg) end
self.ui['score_bg'] = UiWindow(0,'score_bg',0,0,180,40,'0:7')
if self.ui.debug then UiDelete(self.ui.debug) else self.ui['debug'] = UiWindow(0,"debug",0,0,100,100,'0:7') UiAttachUser(user, self.ui.debug) end
UiImage(self.ui.score_bg,"score_img", 10,-8,SCORE.WIDTH,SCORE.HEIGHT,SCORE.SPRITE)
UiAttachObject(anchor,self.ui.score_bg)
self.ui['score'] = UiFontLabel(self.ui.score_bg,"score_text",10,10,tostring(self.score),GetWorld().fontrec_lcd_blue,nil,nil,1)
if self.ui.egg then UiDelete(self.ui.egg) end
self.ui['egg'] = UiImage(0,'egg',0,50,181,46,'0:41')
UiAttachObject(anchor,self.ui.egg)
elseif anchor.anchor_name == 'hi-score' then
self.ui['hi-score_anchor'] = anchor
if self['hi-score_bg'] then UiDelete(self.ui['hi-score_bg']) end
self.ui['hi-score_bg'] = UiWindow(0,'hi-score_bg',0,0,180,40,'0:7')
UiImage(self.ui['hi-score_bg'],"hiscore_img", 10,-8,HISCORE.WIDTH,HISCORE.HEIGHT,HISCORE.SPRITE)
UiAttachObject(anchor,self.ui['hi-score_bg'])
if self.ui.hi_score_text then UiDelete(self.ui.hi_score_text) end
local hiscore = GetWorld().hi_score[1] and GetWorld().hi_score[1].score or 0
self.ui['hi_score_text'] = UiFontLabel(self.ui['hi-score_bg'],"hi_score_text",10,10,tostring(hiscore),GetWorld().fontrec_lcd_blue,nil,nil,1)
elseif anchor.anchor_name == 'lines' then
self.ui['lines_anchor'] = anchor
if self.ui.lines_bg then UiDelete(self.ui.lines_bg) end
self.ui['lines_bg'] = UiWindow(0,'lines_bg',0,0,80,50,'0:7')
UiImage(self.ui.lines_bg,"lines_img", 10,-8,LINES.WIDTH,LINES.HEIGHT,LINES.SPRITE)
UiAttachObject(anchor,self.ui.lines_bg)
self.ui['lines'] = UiFontLabel(self.ui.lines_bg,"lines_text",10,10,tostring(self.lines),GetWorld().fontrec_lcd_blue,nil,nil,1)
elseif anchor.anchor_name == 'level' then
self.ui['level_anchor'] = anchor
if self.ui.level_bg then UiDelete(self.ui.level_bg) end
self.ui['level_bg'] = UiWindow(0,'level_bg',0,0,50,50,'0:7')
UiImage(self.ui.level_bg,"level_img", 10,-8,LEVEL.WIDTH,LEVEL.HEIGHT,LEVEL.SPRITE)
UiAttachObject(anchor,self.ui.level_bg)
self.ui['level'] = UiFontLabel(self.ui.level_bg,"level_text",10,10,tostring(self.level),GetWorld().fontrec_lcd_blue,nil,nil,1)
if self.ui.central then UiDelete(self.ui.central) end
local url = 'http://'..GetPortalHost()..'/images/header_button_central.png'
self.ui.central = UiImageButtonRef(0, 'central', 0, 70, 71, 61, url,url,url,'goto_central')
UiAttachObject(anchor,self.ui.central)
UiAddEffect(self.ui.central,'hover','glow')
elseif anchor.anchor_name == 'egg' then
end
end
end
end
block_spawner
Code: MetaScript
Define Properties()
queue = {}
max_queue = 6
dx = 0
dy = 1
t = 0
last_block = '_object_'
player = '_object_'
grid = '_object_'
lock = 0
buffer={}
data = {}
ui = {}
IncludeScript("21769:58")
end
BLOCK_SPRITE = '0:14'
BLOCKS = {
{name='square',master=0,r=255,g=255,b=0,w=2,h=2,blocks={{x=-1,y=0},{x=0,y=0},{x=0,y=-1},{x=-1,y=-1}}},
{name='line',master=0,r=0,g=255,b=255,w=4,h=1,blocks={{x=-2,y=0},{x=-1,y=0},{x=0,y=0},{x=1,y=0}}},
{name='S',master=1,r=0,g=255,b=0,w=3,h=2,blocks={{x=-1,y=0},{x=0,y=0},{x=0,y=-1},{x=1,y=-1}}},
{name='Z',master=1,r=255,g=0,b=0,w=3,h=2,blocks={{x=-1,y=-1},{x=0,y=-1},{x=0,y=0},{x=1,y=0}}},
{name='L',master=1,r=255,g=128,b=0,w=3,h=2,blocks={{x=-1,y=0},{x=0,y=0},{x=1,y=0},{x=1,y=-1}}},
{name='back-L',master=1,r=0,g=0,b=255,w=3,h=2,blocks={{x=-1,y=0},{x=0,y=0},{x=1,y=0},{x=-1,y=-1}}},
{name='tee',master=1,r=255,g=0,b=255,w=3,h=2,blocks={{x=-1,y=0},{x=0,y=0},{x=1,y=0},{x=0,y=-1}}},
}
NEXT = {SPRITE='0:33',WIDTH=55,HEIGHT=18}
HOLD = {SPRITE='0:36',WIDTH=55,HEIGHT=18}
MEEP = '0:40'
--triggers
Trigger init(user)
if (self.player == nil and user ~= nil) or (user ~= nil and (self.player ~= nil and self.player ~= user) ) or (self.player ~= nil and user == nil ) then
if (self.player == nil and user ~= nil) or (user ~= nil and (self.player ~= nil and self.player ~= user) ) then
self.player = user
user.spawner = self
end
table.clear(self.data)
table.clear(self.queue)
for i = 1,self.max_queue do
math.randomseed(Now()*i)
local rand = math.random(1,#BLOCKS)
table.insert(self.queue,table.deepcopy(BLOCKS[rand]))
end
--create ui
local w = GetWorld()
local size = 64*GetPlace().zoom
local s = (size + 2) * 4
local anchors = FindObjectsInPlaceById(GetPlace(), '0:8')
if anchors then
for _,anchor in ipairs(anchors) do
if anchor.anchor_name == 'block_queue' then
self.ui['queue_anchor'] = anchor
if self.ui.block_queue then UiDelete(self.ui.block_queue) end
self.ui['block_queue'] = UiElement(0,'block_queue',0,0)
UiAttachObject(anchor,self.ui.block_queue)
UiImage(self.ui.block_queue, 'queue_arrow', -size,0, size,s,'0:16')
for i=1,self.max_queue do
local x = i < 2 and 0 or s
local y = i > 1 and s*(i-2) or 0
self.ui['queue'..i] = UiWindow(self.ui.block_queue,'block'..i,x,y,s,s,'0:7')
if i == 1 then
UiImage(self.ui['queue'..i],"next_img", 10,-8,NEXT.WIDTH,NEXT.HEIGHT,NEXT.SPRITE)
end
end
elseif anchor.anchor_name == 'hold' then
self.ui['hold_anchor'] = anchor
if self.ui.hold_bg then UiDelete(self.ui.hold_bg) end
self.ui['hold_bg'] = UiWindow(0,"hold_win_bg",0,0,s,s,"0:7")
UiImage(self.ui.hold_bg,"hold_img", 10,-8,HOLD.WIDTH,HOLD.HEIGHT,HOLD.SPRITE)
UiAttachObject(anchor,self.ui.hold_bg)
elseif anchor.anchor_name == 'profile' then
self.ui['profile_anchor'] = anchor
if self.ui.profile_bg then UiDelete(self.ui.profile_bg) end
self.ui['profile_bg'] = UiWindow(0,'profile_bg',0,0,s,s,'0:7')
local img = GetUserImage(self.player)
local offset = 10
self.ui['profile_img'] = UiImageRef(self.ui.profile_bg,'profile_img',offset,offset,s-(2*offset),s-(2*offset),img)
UiAttachObject(anchor,self.ui.profile_bg)
else
end
end
end
else
DestroyObject(self)
end
end
Trigger start_game()
self.grid.game_status = 1
SendTo(self,'create_block', 0)
end
Trigger enter()
--SendTo(self,'init',0)
end
Trigger destroyed()
for i,v in ipairs(self.grid.spawners) do
if v == self then
table.remove(self.grid.spawners,i)
end
end
UiDelete(self.ui.block_queue)
UiDelete(self.ui.hold_bg)
UiDelete(self.ui.profile_bg)
end
Trigger lock()
self.lock = 1
table.clear(self.buffer)
if self.last_block then
self.last_block.pause = 1
end
end
Trigger unlock()
self.lock = 0
--process queue
for i,v in ipairs(self.buffer) do
SendTo(self,v.trigger,0)
end
table.clear(self.buffer)
if self.last_block then
self.last_block.pause = 0
if self.last_block.callback_loop ~= 0 then
CancelSend(self.last_block, self.last_block.callback_loop)
self.last_block.callback_loop = 0
end
SendTo(self.last_block, 'move_tick', 0)
else
SendTo(self,'create_block',0)
end
end
Trigger create_block(hold)
if self.grid.game_status == 1 then
if self.lock == 0 then
if self.last_block == nil then
--if self.t == 1 then
local pattern = {}
if hold == 1 and self.data.hold_switch then
pattern = self.data.hold_switch
self.data.hold_switch = nil
else
if #self.queue > 0 then
pattern = table.remove(self.queue, 1)
math.randomseed(Now())
table.insert(self.queue,table.deepcopy(BLOCKS[math.random(1,#BLOCKS)]))
end
end
if pattern.blocks then
self.data['current'] = pattern
if hold == 1 then
self.data.current['hold'] = true
end
local d_x = 0
local d_y = 0
if pattern.master == 0 then
d_x = 0.5
d_y = 0.5
end
local master = CreateObjectById('0:5', self.x-d_x, self.y-d_y, self.z, 0)
self.last_block = master
master.dx = self.dx
master.dy = self.dy
master.spawner = self
local interval = self.grid.interval - (self.grid.level*100)
if interval < 50 then interval = 50 end
master.interval = interval
master.tint_r = pattern.r or 0
master.tint_g = pattern.g or 0
master.tint_b = pattern.b or 0
--Debug(pattern.name)
for i,v in ipairs(pattern.blocks) do
local block = CreateObjectById('0:4', master.x+v.x+d_x, master.y+v.y+d_y, self.z, 0)
if self.player.meeper == 1 then
block.spriteId = MEEP
end
local r = pattern.r == 0 and 192 or pattern.r
local g = pattern.g == 0 and 192 or pattern.g
local b = pattern.b == 0 and 192 or pattern.b
TintSprite(block, 'none', r, g, b)
--AddEffect(block,"always","glow",{red=pattern.r,green=pattern.g,blue=pattern.b,strength=5})
block.parent = master
block.grid = self.grid
table.insert(master.children, block)
end
if hold ~= 1 then
for i=1,self.max_queue do
if self.ui['queue'..i..'_b'] ~= 0 and self.ui['queue'..i..'_b']~= nil then
if i == 1 then
if self.ui.current_block then
UiDelete(self.ui.current_block)
end
UiVisible(self.ui['queue'..i..'_b'], 0)
self.ui['current_block'] = self.ui['queue'..i..'_b']
else
UiDelete(self.ui['queue'..i..'_b'])
end
end
self.ui['queue'..i..'_b'] = block_ui(self, i, self.ui['queue'..i],nil, GetPlace().zoom)
-- local vis = i==self.max_queue and 200 or 0
--UiVisible(self.ui['queue'..i..'_b'],1,vis)
end
end
SendTo(master, 'move_tick', 0)
end
--end
else
Debug('DING')
end
else
--locked. buffer action
table.insert(self.buffer,{trigger='create_block'})
end
end
end
Trigger rotate_block(wise)
if self.last_block then
SendTo(self.last_block,'rotate_block', 0, wise)
end
end
Trigger move_block(dir)
if self.last_block then
SendTo(self.last_block,'move_block', 0, dir)
end
end
Trigger hold()
if not self.data.current.hold then
self.player.continous_move = 0
self.player.continous_moves = 0
self.player.continous_move_down = 0
local cur_data = table.deepcopy(self.data['current'])
local hold_data = table.deepcopy(self.data['hold'])
self.data['hold_switch'] = hold_data
local cur_ui = self.ui.current_block
local hold_ui = self.ui.hold_block
self.data['hold'] = cur_data
SendTo(self.last_block,'kill_block',0)
self.last_block = nil
UiDelete(cur_ui)
self.ui['hold_block'] = block_ui(self, 'hold', self.ui.hold_bg, cur_data, GetPlace().zoom)
UiVisible(self.ui.hold_block, 1)
self.ui['current_block'] = hold_ui
UiVisible(self.ui.current_block, 0)
local h_data = 0
if hold_data then h_data = 1 Debug('hold data') end
SendTo(self, 'create_block',100,h_data)
else
Debug('hold blocked')
end
end
--functions
function block_ui(self, pos, parent,data,scale)
parent = parent or 0
local block = data or self.queue[pos]
local size = 64*scale
local s = (size + 2) * 4
local b = UiWindow(parent,'block'..pos,0,0,s,s,'0:17')
local _,ox2 = math.modf(block.w/2)
local _,oy2 = math.modf(block.h/2)
for i,v in ipairs(block.blocks) do
local offset_x = ox2 == 0 and v.x*size or v.x*size - (size/2)
local offset_y = oy2 == 0 and v.y*size or v.y*size - (size/2)
local sprite = self.player.meeper == 1 and MEEP or BLOCK_SPRITE
local img = UiImage(b, 'b_'..pos..'_'..i, (s/2)+offset_x, (s/2)+offset_y, size, size, sprite)
UiTint(img,block.r,block.g,block.b)
end
return b
end
master_block
Code: MetaScript
Define Properties()
children = {}
spawner = '_object_'
path_blocked = 0
rot_blocked = 0
interval = 1000
dx = 0
dy = 0
lock = 0
tint_r = 0
tint_g = 0
tint_b = 0
pause = 0
callback_loop = 0
last_tick = 0
itt = 0
end
Trigger move_tick(once)
move_tick(self)
if self.callback_loop ~= 0 then
CancelSend(self, self.callback_loop)
self.callback_loop = 0
end
if not once then
local interval = self.interval
if self.lock == 1 then
if self.interval * 2 < self.spawner.grid.interval then
interval = self.interval * 2
end
end
local c = SendToRepeat(self, 'move_tick_loop', interval)
if c ~= 0 then
self.callback_loop = c
end
end
end
Trigger move_tick_loop()
if self.pause == 0 then
move_tick(self)
else
CancelSend(self, self.callback_loop)
self.callback_loop = 0
end
end
function move_tick(self)
if self.pause == 0 then
self.path_blocked = 0
if self.spawner.player.continous_move_down == 0 then
SendToTable(self.children, 'move_check', 0, self.dx, self.dy)
if self.path_blocked == 0 and self.lock ~= 2 then
self.lock = 0
SendToTable(self.children, 'move_block', 0, self.dx, self.dy)
MoveObject(self, self.x+self.dx, self.y+self.dy, self.z, 1)
else
if self.itt == 0 and self.lock ~= 2 then
self.spawner.grid.game_status = 0
CancelSend(self, self.callback_loop)
set_block(self, true)
SendTo(self.spawner.grid,'game_over',0,self.spawner)
return
end
if self.lock > 0 then
set_block(self)
return
else
self.lock = 1
end
end
end
end
self.itt = self.itt + 1
end
Trigger kill_block()
kill_block(self)
end
Trigger move_block(dir)
if self.pause == 0 and #self.children > 0 and self.lock ~= 2 then
self.lock = 0
local dx = 0
local dy = 0
if dir == 'up' then
local drop = drop_move(self)
self.lock = 2
SendTo(self.spawner.grid, 'update_score',0,drop*2)
set_block(self)
return
elseif dir == 'down' then
dx = self.dx
dy = self.dy
else
if self.dx == 0 then
if self.dy > 0 then
if dir == 'left' then
dx = -1
elseif dir == 'right' then
dx = 1
end
elseif self.dy < 0 then if dir == 'left' then dx = 1 elseif dir == 'right' then dx = -1 end end
elseif self.dy == 0 then
if self.dx > 0 then if dir == 'left' then dy = -1 elseif dir == 'right' then dy = 1 end
elseif self.dx < 0 then if dir == 'left' then dy = 1 elseif dir == 'right' then dy = -1 end end
end
end
self.path_blocked = 0
SendToTable(self.children, 'move_check', 0, dx, dy)
if self.path_blocked == 0 then
SendToTable(self.children, 'move_block', 0, dx, dy)
MoveObject(self, self.x+dx, self.y+dy, self.z, 1)
if dir == 'down' then
SendTo(self.spawner.grid, 'update_score',0,1)
end
else
if dir == 'down' then
self.lock = 2
set_block(self)
else
self.lock = 1
end
end
end
end
Trigger rotate_block(wise)
if self.pause == 0 and #self.children > 0 and self.lock ~= 2 then
self.lock = 0
rotate_block_eval(self,wise,1)
end
end
--functions
function rotate_block_eval(self,wise,it)
it = it or 1
self.rot_blocked = 0
local p = {{x=0,y=0}}
if self.dx == 0 then
local d_x = wise == 'anti' and -self.dy or self.dy
p[2] = {x=d_x,y=0}
p[3] = {x=d_x,y=-self.dy}
p[4] = {x=0,y=-self.dy}
elseif self.dy == 0 then
local d_y = wise == 'anti' and -self.dx or self.dx
p[2] = {x=0,y=d_y}
p[3] = {x=-self.dx,y=d_y}
p[4] = {x=-self.dx,y=0}
end
if p[it] then
local dx = p[it].x
local dy = p[it].y
check_rotation(self, wise, dx, dy)
if self.rot_blocked == 1 then
it = it + 1
rotate_block_eval(self,wise,it)
else
rotate_blocks(self, wise, dx, dy)
end
end
end
function check_rotation(self, wise, d_x, d_y)
for i,block in ipairs(self.children) do
local dx = self.x - block.x
local dy = self.y - block.y
local nx, ny = rot_pos(dx, dy, wise)
SendTo(block,'rot_check',0,self.x+nx+d_x, self.y+ny+d_y,1)
end
end
function rotate_blocks(self, wise, d_x, d_y)
for i,block in ipairs(self.children) do
local dx = self.x - block.x
local dy = self.y - block.y
local nx, ny = rot_pos(dx, dy, wise)
MoveObject(block,self.x+nx+d_x, self.y+ny+d_y, block.z, 1)
end
MoveObject(self,self.x+d_x, self.y+d_y, self.z+5, 1)
end
function rot_pos(dx, dy, wise)
local da = wise == 'anti' and -1 or 1
local nx = -dy*da
local ny = dx*da
return nx, ny
end
function drop_move(self)
self.path_blocked = 0
local dx = 0
local dy = 0
local drop = 0
local lim = 0
if self.dx == 0 then
lim = self.spawner.grid.t_grid_y2 - self.spawner.grid.t_grid_y1
elseif self.dy == 0 then
lim = self.spawner.grid.t_grid_x2 - self.spawner.grid.t_grid_x1
end
for i=1,lim+1 do
SendToTable(self.children, 'move_check', 0, self.dx*i, self.dy*i)
if self.path_blocked == 1 then
dx = self.dx*(i-1)
dy = self.dy*(i-1)
break
end
drop = drop + 1
end
SendToTable(self.children, 'move_block', 0, dx, dy)
MoveObject(self, self.x+dx, self.y+dy, self.z, 1)
return drop
end
function kill_block(self)
for _,v in ipairs(self.children) do
DestroyObject(v)
end
DestroyObject(self)
end
function eval_drop(self)
local lines = {}
table.clear(self.spawner.grid.eval_buffer)
for _,block in ipairs(self.children) do
lines[block[self.spawner.grid.eval_dir]] = block[self.spawner.grid.eval_dir]
end
for _,l in pairs(lines) do
SendTo(self.spawner.grid,'eval_drop',0,l,self.spawner)
end
SendTo(self.spawner.grid,'eval_clean',0,self.spawner)
end
function set_block(self, dne)
self.spawner.player.continous_move = 0
self.spawner.player.continous_moves = 0
self.spawner.player.continous_move_down = 0
SendToTable(self.children, 'release_children', 0)
if not dne then
eval_drop(self)
end
table.clear(self.children)
self.spawner.last_block = nil
SendTo(self.spawner, 'create_block', 10)
DestroyObject(self)
end
block
Code: MetaScript
Define Properties()
parent = "_object_"
grid = "_object_"
end
Trigger move_check(dx, dy)
local blocked = pos_check(self,self.x+dx,self.y+dy)
if blocked then
self.parent.path_blocked = 1
end
end
Trigger rot_check(dx,dy,abs)
local x = abs == 1 and dx or self.x+dx
local y = abs == 1 and dy or self.y+dy
local blocked = pos_check(self,x,y)
if blocked then
self.parent.rot_blocked = 1
end
end
Trigger move_block(dx, dy)
MoveObject(self, self.x+dx, self.y+dy, self.z, 1)
end
Trigger release_children()
TintSprite(self, 'none', self.parent.tint_r, self.parent.tint_g, self.parent.tint_b)
self.parent = nil
end
function pos_check(self, x, y)
if IsTileClear(x,y) == 0 then
local obj = GetObjectAt(x,y)
if obj then
if obj and obj.parent and obj.parent == self.parent then
return false
end
return true
else
return true
end
end
return false
end
tfbg.php
Code: php
<?php
$host = "api.metaplace.com";
$rest = "/api/v0.2/public/game/invoke/trigger/thatfallingblockgame/scoreboard/world/0/".($_GET['interval']?"interval=".(int)$_GET['interval']:'');
$header = "GET $rest HTTP/1.0\r\n";
$header .= "Host: ".$host."\r\n";
$header .= "Connection: Close\r\n\r\n";
$url = $host;
$port = 80;
$fp = fsockopen ($url, $port, $errno, $errstr, 30) or die("Could not connect to ".$host);
fputs ($fp, $header . $req);
$xm = '';
$x = false;
while (!feof($fp))
{
$res = fgets ($fp, 1024);
if( !$x ){
if(preg_match("<scores>",$res))
$x = true;
}
if( $x )
$xm .= $res;
}
$xml = simplexml_load_string($xm);
fclose( $fp );
if($xml) {
$size = 24;
$img = imagecreatetruecolor(350,($size+4)*(sizeof($xml)+1));
imageantialias($img, true);
imagealphablending($img, true);
imagecolortransparent($img,imagecolorat($img,0,0));
$red = imagecolorallocate($img, 255, 0, 0 );
$yellow = imagecolorallocate($img, 255, 255, 0 );
$orange = imagecolorallocate($img, 255, 165, 9 );
$black = imagecolorallocate($img, 1, 1, 1 );
$font = "badabb.ttf";
//$font = "arial.ttf";
//$font = "arialbd.ttf";
$i = 1;
$offsetX = 3;
$offsetY = 3;
imagettftext($img, $size, 0, 10-$offsetX, $size+$offsetY, $black, $font, "username:" );
imagettftext($img, $size, 0, 10, $size, $red, $font, "username:" );
imagettftext($img, $size, 0, 160-$offsetX, $size+$offsetY, $black, $font, "score:" );
imagettftext($img, $size, 0, 160, $size, $red, $font, "score:" );
imagettftext($img, $size, 0, 240-$offsetX, $size+$offsetY, $black, $font, "level:" );
imagettftext($img, $size, 0, 240, $size, $red, $font, "level:" );
foreach($xml->score AS $score){
imagettftext($img, $size, 0, 10-$offsetX, (($size+4)*$i)+$size+$offsetY, $black, $font, substr(strval($score->username), 0, 10) );
imagettftext($img, $size, 0, 10, (($size+4)*$i)+$size, $yellow, $font, substr(strval($score->username), 0, 10) );
imagettftext($img, $size, 0, 160-$offsetX, (($size+4)*$i)+$size+$offsetY, $black, $font, strval($score->user_score) );
imagettftext($img, $size, 0, 160, (($size+4)*$i)+$size, $orange, $font, strval($score->user_score) );
imagettftext($img, $size, 0, 260-$offsetX, (($size+4)*$i)+$size+$offsetY, $black, $font, (strval($score->level) != '' ? strval($score->level) : '?' ) );
imagettftext($img, $size, 0, 260, (($size+4)*$i)+$size, $yellow, $font, (strval($score->level) != '' ? strval($score->level) : '?' ) );
$i++;
}
header("Content-type: image/png");
imagepng($img);
}
?>
| |
|
| | |
|