Quick Links: Download Gideros Studio | Gideros Documentation | Gideros Development Center | Gideros community chat | DONATE
80's style demos in Gideros - Page 3 — Gideros Forum

80's style demos in Gideros

13»

Comments

  • hgy29hgy29 Maintainer
    This is truly excellent, I frankly didn't expect a tetris in 3k, great job. We have pure gold in this thread, it will be hard to choose which one to publish first. Warm thanks to you all!

    Likes: MoKaLux

    +1 -1 (+1 / -0 )Share on Facebook
  • piepie Member
    Simon says with sounds thanks to PaulH :) Removing tabs the char number drops below 3k but it has become already much more unreadable than before.

    local ns={440,261,293,392}
    function mwav(fn, q)
    	local function wav(p,q)
    		local n = math.floor(math.sin(p/6000 * q * math.rad(180))*256*127)
    		local c2, c1 = (n>>8) & 0xff,n & 0xff
    		return string.char(c1,c2)
    	end
    	f=io.open(fn,"wb")
    	f:write(string.char(82,73,70,70,140, 9, 0, 0,87,65,86,69,102,109,116,32,16,0,0,0,1,0,1,0,112,23,0,0,224,46,0,0,2,0,16,0,100,97,116,97,96,9,0,0))
    	for l = 1, 1200 do f:write(wav(l,q)) end
    	f:close()
    end
     
    application:setBackgroundColor(0x000000)
    math.randomseed(os.timer())
    s, sphrase, sstate, s_counter, usersay, start_time = {}, {}, "idle", 1, {}, os.timer()
    colors = {0xFF0000, 0x0000FF, 0x00FF00, 0xFFFF00}
    s_sector = Core.class(Sprite)
    sscale = {{5,5},{-5,5},{-5,-5},{5,-5}}
    function s_sector:init(i)
    self.gfx = Path2D.new()
    self.gfx:setSvgPath("M0.6,17.9c7.6,0,13.8,6.3,13.8,14.1L32,32C32,14.3,17.9,0,0.6,0V17.9z")
    self:addChild(self.gfx)
    self:setAnchorPoint(-0.01,1)
    self:setScale(sscale[i][1], sscale[i][2])
    self.i = i 
    self.gfx:setFillColor(colors[i],.5)
    	self:addEventListener(Event.ENTER_FRAME, function() 
    			local dt = os.timer()-start_time
    			if dt >0.5 and dt <0.6 then self.gfx:setFillColor(colors[i],.5) end
    		end)
    end
    for i=1,4 do
    	s[i] = s_sector.new(i)
    	stage:addChild(s[i])
    	s[i]:setPosition(200,250)
    	local b=Buffer.new(i..".wav")
    	mwav("|B|"..i..".wav", ns[i], 1)
    	ns[i] = Sound.new("|B|"..i..".wav")
    end
    play = TextField.new(nil, "PLAY")
    play:setTextColor(0xFFFFFF)
    play:setScale(2)
    play:setPosition(20,20)
    stage:addChild(play)
    stage:addEventListener(Event.MOUSE_DOWN, function(e)
    										if sstate == "wait" then
    											for i in ipairs(s) do 
    												if s[i].gfx:hitTestPoint(e.x, e.y) then	
    													ns[i]:play() -- bip
    													usersay[#usersay+1] = i
    													if sphrase[#usersay] == i then
    														s[i].gfx:setFillColor(colors[i],1)
    														if #usersay == #sphrase then
    															sstate = "add"
    														end
    													else
    														play:setText("YOU LOST AT LEVEL "..#sphrase.."!\nCLICK HERE TO TRY AGAIN")
    														sstate = "idle"
    													end
    												end
    											end
    										end
    										if play:hitTestPoint(e.x,e.y) then
    											play:setText("SIMON'S TURN")
    											sphrase = {}
    											usersay = {}
    											s_counter = 1
    											sstate = "add"
    										end
    									end)
    stage:addEventListener(Event.MOUSE_UP, function(e)
    										for i in ipairs(s) do 
    												if s[i]:hitTestPoint(e.x, e.y) then	s[i].gfx:setFillColor(colors[i],.5)	end
    										end
    									end)
    stage:addEventListener(Event.ENTER_FRAME, function()
    										if sstate == "go" then
    											if  os.timer()-start_time >0.7 then
    													if s_counter <=#sphrase then
    														ns[sphrase[s_counter]]:play() --bip
    														s[sphrase[s_counter]].gfx:setFillColor(colors[sphrase[s_counter]],1)
    														start_time = os.timer()	
    													end
    													if s_counter == #sphrase then
    														sstate = "wait"
    														play:setText("YOUR TURN")
    													else
    														sstate = "next"	
    														play:setText("SIMON'S TURN")
    													end
    											end	
    										elseif sstate == "add" then
    											sphrase[#sphrase+1]=math.random(4)
    											s_counter, usersay, sstate, start_time = 1, {}, "go", os.timer()
    										elseif sstate == "next" then
    											s_counter, sstate = s_counter+1, "go"
    										end
    									end)

    Likes: PaulH, MoKaLux

    +1 -1 (+2 / -0 )Share on Facebook
  • keszegh said:

    rrraptor said:

    keszegh said:

    i did not expect a tetris in 3k. great thread.

    A bit more :smiley: I updated the code, now it is 3279 (114 lines) (before: 3317 (115))
    you could separately share the imgui version, it could give ideas for us how to use the imgui graphics functions.
    3062
    require "ImGui"
    ui=ImGui.new()
    application:setWindowSize(320,720)
    ui:getIO():setDisplaySize(320,720)
    stage:addChild(ui)
    GS,SC,MSC,TR,TS,CM,KC,BR,ST=0,0,0,0,1,false,KeyCode,{},{[0]=0,40,100,300,1200}
    BR=table.create(21)
    for i=1,20 do BR[i]=table.create(10,0) end
    BR[21]=table.create(10,8)
    TES={
    	{0x00F0F0,{{0,0,0,0},{1,1,1,1},{0,0,0,0},{0,0,0,0}}}, {0x0000F0,{{1,0,0},{1,1,1},{0,0,0}}},
    	{0xF0A000,{{0,0,1},{1,1,1},{0,0,0}}}, {0xF0F000,{{1,1},{1,1}}},
    	{0x00F000,{{0,1,1},{1,1,0},{0,0,0}}}, {0xA000F0,{{0,1,0},{1,1,1},{0,0,0}}},
    	{0xF00000,{{1,1,0},{0,1,1},{0,0,0}}}, {0x323232}
    }
    T={i=0,x=4,y=1,d=0}
    function forT(t,c) 
    	for y=1,#t do for x=1,#t[1] do 
    		if t[y][x]>0 then 
    			local r=c(x,y) 
    			if r~=nil then return r end 
    		end 
    	end end 
    end
    function over(t,tx,ty,td)
    	return forT(td,function(x,y)
    		local bv=t[ty+y-1][tx+x-1]
    		if not bv or bv>0 then return true end 
    end)
    end
    function put(t,tx,ty,td,n) forT(td,function(x,y) t[ty+y-1][tx+x-1]=n end) end
    function trMv(x,y,nb)
    	local tb={}
    	for i=1,21 do tb[i]={} for j=1,10 do tb[i][j]=BR[i][j] end end
    	put(tb,T.x,T.y,T.d,0)
    	if not over(tb,x,y,nb) then
    		put(BR,T.x,T.y,T.d,0)
    		put(BR,x,y,nb,T.i)
    		return true
    	end
    end
    function mv(dx, dy)
    	local nx,ny=T.x+dx,T.y+dy
    	if trMv(nx,ny,T.d) then 
    		T.x,T.y=nx,ny
    		return true 
    	end
    end
    stage:addEventListener("keyDown", function(e)
    	if e.keyCode==KC.SPACE and GS==0 then GS=1 end
    	if not CM then return end
    	if e.keyCode==KC.DOWN then TS=0.05
    	elseif e.keyCode==KC.UP then
    		local nb={}
    		for i=#T.d[1],1,-1 do
    			nb[i]={}
    			for j=1,#T.d do nb[i][j]=T.d[#T.d-j+1][i] end 
    		end
    		if trMv(T.x,T.y,nb) then T.d=nb end
    	elseif e.keyCode==KC.LEFT then mv(-1,0)
    	elseif e.keyCode==KC.RIGHT then mv(1,0) 
    	end
    end)
    stage:addEventListener("keyUp", function(e) if e.keyCode==KC.DOWN then TS=1 end end)
    stage:addEventListener("enterFrame", function(e)
    	ui:newFrame(e.deltaTime)
    	TR+=e.deltaTime
    	if TR>0.4*TS then
    		TR=0
    		if GS==1 then
    			T.x,T.y,T.i=4,1,math.random(1, 7)
    			T.d=TES[T.i][2]
    			if over(BR,T.x,T.y,T.d) then
    				for i=1,m or 20 do for j=1,10 do BR[i][j]=0 end end
    				GS,SC,CM=0,0,false
    			else
    				put(BR,T.x,T.y,T.d,T.i)
    				GS,CM=2,true
    			end
    		elseif GS==2 then
    			if not mv(0,1) then
    				local r=0
    				for y=1,20 do
    					local c=0
    					for x=1,10 do if BR[y][x]>0 then c+=1 end end
    					if c == 10 then
    						table.remove(BR,y)
    						table.insert(BR,1,table.create(10,0))
    						r+=1
    					end
    				end
    				SC+=ST[r]
    				MSC=MSC<>SC
    				GS,CM=1,false
    			end
    		end
    	end
    	local list=ui:getForegroundDrawList()
    	local text="Press 'Space' to start"
    	if GS==0 then text=`Score: {SC} Max: {MSC}\n{text}`
    	else text=`Score: {SC} Max: {MSC}` end
    	list:addText(10,3,0,1,text)
    	for i,r in ipairs(BR) do
    		for j,c in ipairs(r) do
    			if c>0 then 
    				list:addRectFilled((j-1)*32,i*32,j*32,(i+1)*32,TES[c][1])
    				list:addRect((j-1)*32,i*32,j*32,(i+1)*32,0,0.5,2)
    			end
    		end
    	end
    	list:addLine(0,32,320,32,0,1)
    	ui:render()
    	ui:endFrame()
    end)
    +1 -1 (+5 / -0 )Share on Facebook
  • @rrraptor Unbelievable! I still reading to find out why these 114 lines of code can have a complicated "rotate clamp in the boundary" feature! Thank you so much!
    Coming soon
  • rrraptorrrraptor Member
    edited May 2023

    @rrraptor Unbelievable! I still reading to find out why these 114 lines of code can have a complicated "rotate clamp in the boundary" feature! Thank you so much!

    At the bottom I hardcoded a wall. For left & right boundaries the trick is that I copy the whole board into a temporary array (the "trMv" function aka "tryMove"), then I "erase" the current piece from it and check for a collision with something (but in a new position), there is also a check for out of bounds by checking for "nil" (however in the code I wrote it as "not bv" aka "boardValue ~= nil") in "over" function (aka "overlap")

    Here is uncut version (with imgui):
    require "ImGui"
     
    -- Constants --
    BOARD_W = 10
    BOARD_H = 20
    TILE = 32
     
    -- Global variables --
     
    -- values for 'GameState' variable
    States = { 
    	GAME_OVER = 0,
    	SPAWN = 1,
    	REMOVE_LINES = 2
    }
    GameState = 0 
    GameSpeed = 0.4 -- lower -> faster
    SpeedUPFactor = 0.05 -- GameSpeed multiplier when holding 'Down' (lower -> faster)
    Score = 0
    MaxScore = 0
    Timer = 0
    TimerScale = 1
    CanMove = false
    ScoreTable = {[0]=0,40,100,300,1200} -- how many scores player get for burning N lines
     
    -- initialize simple matrix
    Board = table.create(BOARD_H + 1)
    for i=1, BOARD_H do 
    	Board[i] = table.create(BOARD_W, 0) 
    end
    Board[BOARD_H + 1] = table.create(BOARD_W,8) -- Floor
     
    Tetrominos = {
    	{ -- I
    		color = 0x00F0F0, data = {
    			{0,0,0,0},
    			{1,1,1,1},
    			{0,0,0,0},
    			{0,0,0,0}
    		}
    	},
    	{ -- J
    		color = 0x0000F0, data = {
    			{1,0,0},
    			{1,1,1},
    			{0,0,0}
    		}
    	},
    	{ -- L
    		color = 0xF0A000, data = {
    			{0,0,1},
    			{1,1,1},
    			{0,0,0}
    		}
    	}, 
    	{ -- O
    		color = 0xF0F000, data = {
    			{1,1},
    			{1,1}
    		}
    	},
    	{ -- S
    		color = 0x00F000, data = {
    			{0,1,1},
    			{1,1,0},
    			{0,0,0}
    		}
    	}, 
    	{ -- T
    		color = 0xA000F0, data = {
    			{0,1,0},
    			{1,1,1},
    			{0,0,0}
    		}
    	},
    	{ -- Z
    		color = 0xF00000, data = {
    			{1,1,0},
    			{0,1,1},
    			{0,0,0}
    		}
    	},
    	-- Floor color
    	{0x323232}
    }
    CurrentTetromino = {
    	index = 0, -- index in 'Tetrominos' table
    	x = 4, -- position
    	y = 1, 
    	data = 0 -- data from 'Tetrominos' table
    }
     
    ui=ImGui.new()
    IO = ui:getIO()
    stage:addChild(ui)
     
    function forEachTetromino(tetData, callback)
    	local h = #tetData
    	local w = #tetData[1]
    	for y=1, h do 
    		for x=1, w do 
    			if tetData[y][x] > 0 then 
    				local returnValue = callback(x, y) 
    				if returnValue ~= nil then 
    					return returnValue
    				end 
    			end 
    		end 
    	end 
    end
     
    function overlap(board, tx, ty, tetData)
    	return forEachTetromino(tetData, function(x, y)
    		local boardValue = board[ty + y - 1][tx + x - 1]
    		if boardValue == nil or boardValue > 0 then 
    			return true 
    		end
    	end)
    end
     
    function setBoard(board, tx, ty, tetData, value)
    	forEachTetromino(tetData, function(x, y)
    		board[ty + y - 1][tx + x - 1] = value
    	end)
    end
     
    function tryMove(dstX, dstY, tetData)
    	-- copy 'Board' to temp table
    	local tempBoard = {}
    	for i=1,BOARD_H + 1 do
    		tempBoard[i] = {}
    		for j = 1, BOARD_W do
    			tempBoard[i][j] = Board[i][j]
    		end
    	end
     
    	-- remove current piece from temp board
    	setBoard(tempBoard, CurrentTetromino.x, CurrentTetromino.y, CurrentTetromino.data, 0)
    	-- check for collisions at destination point
    	if not overlap(tempBoard, dstX, dstY, tetData) then
    		-- erase data at old position
    		setBoard(Board, CurrentTetromino.x, CurrentTetromino.y, CurrentTetromino.data, 0)
    		-- add data at new position
    		setBoard(Board, dstX, dstY, tetData, CurrentTetromino.index)
    		return true
    	end
    end
     
    function move(dx, dy)
    	local nx = CurrentTetromino.x + dx
    	local ny = CurrentTetromino.y + dy
     
    	if tryMove(nx, ny, CurrentTetromino.data) then 
    		CurrentTetromino.x = nx
    		CurrentTetromino.y = ny
    		return true 
    	end
    end
     
    function onAppResize()
    	local minX, minY, maxX, maxY = application:getLogicalBounds()
    	local screenW = maxX - minX
    	local screenH = maxY - minY
    	BoardOffsetX = (screenW - TILE * BOARD_W) * 0.5
    	BoardOffsetY = (screenH - TILE * BOARD_H) * 0.5
    	IO:setDisplaySize(screenW, screenH)
    end
     
    function onKeyDown(e)
    	if e.keyCode == KeyCode.SPACE and GameState == States.GAME_OVER then 
    		GameState = States.SPAWN
    	end
     
    	if not CanMove then 
    		return
    	end
     
    	if e.keyCode == KeyCode.DOWN then 
    		TimerScale = SpeedUPFactor
    	elseif e.keyCode == KeyCode.UP then
    		-- roatate current piece
    		local rotatedData = {}
    		local h = #CurrentTetromino.data
    		local w = #CurrentTetromino.data[1]
     
    		for i = w, 1, -1 do
    			rotatedData[i] = {}
    			for j = 1, h do 
    				rotatedData[i][j] = CurrentTetromino.data[h - j + 1][i] 
    			end
    		end
     
    		-- if there is no collision between rotated piece and something else, update current data
    		if tryMove(CurrentTetromino.x, CurrentTetromino.y, rotatedData) then 
    			CurrentTetromino.data = rotatedData
    		end
    	elseif e.keyCode == KeyCode.LEFT then
    		move(-1, 0)
    	elseif e.keyCode == KeyCode.RIGHT then
    		move(1, 0) 
    	end
    end
     
    function onKeyUp(e) 
    	if e.keyCode == KeyCode.DOWN then 
    		TimerScale = 1 
    	end
    end
     
    function onEnterFrame(e)
    	local dt = e.deltaTime
     
    	Timer += dt
    	if Timer > GameSpeed * TimerScale then
    		Timer = 0
     
    		if GameState == States.SPAWN then
    			CurrentTetromino.x = math.round(BOARD_W / 2)
    			CurrentTetromino.y = 1
    			CurrentTetromino.index = math.random(#Tetrominos - 1)
    			CurrentTetromino.data = Tetrominos[CurrentTetromino.index].data
     
    			if overlap(Board, CurrentTetromino.x, CurrentTetromino.y, CurrentTetromino.data) then
    				for i = 1, BOARD_H do 
    					for j=1, BOARD_W do 
    						Board[i][j] = 0 
    					end
    				end
     
    				GameState = States.GAME_OVER
    				Score = 0
    				CanMove = false
    			else
    				setBoard(Board, CurrentTetromino.x, CurrentTetromino.y, CurrentTetromino.data, CurrentTetromino.index)
    				GameState = States.REMOVE_LINES
    				CanMove = true
    			end
    		elseif GameState == States.REMOVE_LINES then
    			if not move(0, 1) then
    				local rowsRemoved = 0
     
    				for y = 1, BOARD_H do
    					local columnsFilled = 0
     
    					for x = 1, BOARD_W do 
    						if Board[y][x] > 0 then 
    							columnsFilled += 1 
    						end
    					end
     
    					if columnsFilled == BOARD_W then
    						table.remove(Board, y)
    						table.insert(Board, 1, table.create(BOARD_W, 0))
    						rowsRemoved += 1
    					end
    				end
     
    				Score += ScoreTable[rowsRemoved]
    				MaxScore = MaxScore <> Score
    				GameState = States.SPAWN
    				CanMove = false
    			end
    		end
    	end
     
    	-- rendering with ImGui
    	ui:newFrame(dt)
    	local list = ui:getForegroundDrawList()
    	local text = "Press 'Space' to start"
    	if GameState == States.GAME_OVER then 
    		text=`Score: {Score} Max: {MaxScore}\n{text}`
    	else
    		text=`Score: {Score} Max: {MaxScore}`
    	end
    	list:addText(10, 3, 0, 1, text)
     
    	for i, row in ipairs(Board) do
    		for j, cell in ipairs(row) do
    			if cell > 0 then 
    				local sx = BoardOffsetX + (j - 1) * TILE
    				local sy = BoardOffsetY + (i - 1) * TILE
    				local ex = BoardOffsetX + j * TILE
    				local ey = BoardOffsetY + i * TILE
    				list:addRectFilled(sx, sy, ex, ey, Tetrominos[cell].color or 0)
    				list:addRect(sx, sy, ex, ey,0, 0.5, 2)
    			end
    		end
    	end
    	list:addRect(BoardOffsetX, BoardOffsetY, BoardOffsetX + TILE * BOARD_W, BoardOffsetY + TILE * BOARD_H, 0, 1)
    	ui:render()
    	ui:endFrame()
    end
     
    onAppResize()
    stage:addEventListener("applicationResize", onAppResize)
    stage:addEventListener("keyDown", onKeyDown)
    stage:addEventListener("keyUp", onKeyUp)
    stage:addEventListener("enterFrame", onEnterFrame)
    +1 -1 (+4 / -0 )Share on Facebook
  • MoKaLuxMoKaLux Member
    I prefer latest rrraptor code, much more readable :p
    Imho it is less scary (easier to explain) than all the funky code you guys posted.

    So what is the goal, oneliners or short elegant Gideros games?

    My two cents given I haven't produced anything yet :)
    my growING GIDEROS github repositories: https://github.com/mokalux?tab=repositories
  • keszeghkeszegh Member
    edited May 2023
    we could provide director's cuts (or uncut?) when possible, which are mostly the same code but more readable.

    Likes: MoKaLux, pie, PaulH, hgy29

    +1 -1 (+4 / -0 )Share on Facebook
  • hgy29hgy29 Maintainer
    I've had a go at making a first single sheet short gideros code publication. For the first one, I choosed @PaulH plane game, I'll publish it on the internet and see if that gets some attention. If so, maybe we could make a poll to choose next publications.
    Here is the first link: https://wiki.gideros.rocks/images/d/d1/Short-Issue1-Overheat.pdf

    Likes: pie

    +1 -1 (+1 / -0 )Share on Facebook
  • the line numbers should not be in the same block as the codes, as then one cannot copy-paste.
  • hgy29hgy29 Maintainer
    keszegh said:

    the line numbers should not be in the same block as the codes, as then one cannot copy-paste.

    Well, you are not supposed to copy-paste, but to retype it, as if it was printed...
  • hgy29hgy29 Maintainer
    keszegh said:

    i understand the idea, but let's be realistic..

    Agreed, but this fact is I just don't know how to separate the numbering from the text block, since numbering was done automatically by MS Publisher
Sign In or Register to comment.