Mit Minetest den Retroklassiker Snake programmieren

Was mit Minetest alles machbar ist, beweist schön das von SGVsbG8K programmierte Snake-Spiel, bei dem es darum geht, eine Schlange den nächsten Stein fressen zu lassen, wodurch sie immer länger wird. Mit seiner Genehmigung dokumentieren wir hier den Code und ermutigen zum Nachmachen .

Man erreicht es über den POI „Snakespiel“ im Inventar (P anklicken).

Programmierung

Code für die Leuchtsteine auf der Anzeigetafel, unterster Controller:

if event.type=="program" then
mem.pos={0,7}
end
local function is_this(pos)
return (pos[1]==mem.pos[1] and pos[2]==mem.pos[2]) or pos=="all"
end

if event.type=="digiline" and event.channel=="screen" and is_this(event.msg[1]) then
port.c=event.msg[2]
end

Code des Spiels:

local function reset()
mem.cursor={0,0}
digiline_send("screen", {"all",false})
digiline_send("screen", {mem.cursor,true})
mem.length=0
mem.tail={{0,0}}
mem.dir={1,0}
mem.dirname="left"
mem.food={math.random(0,mem.w-1), math.random(0,mem.h-1)}
digiline_send("screen", {mem.food,true})
if not mem.running then interrupt(1);mem.running=true end


end
if event.type=="program" then
mem.name="anonym"
mem.w=8
mem.h=8
mem.dirs={["up"]={0,1},
["down"]={0,-1},
["left"]={1,0},
["right"]={-1,0},}
reset()
end
local function random_pos()
return {math.random(0,mem.w-1), math.random(0,mem.h-1)}

end
local function touching_tail(pos)
for i,j in ipairs(mem.tail) do
if j[1]..","..j[2] ==pos[1]..","..pos[2] then return true end
end
return false
end
local function get_vh(dir)
test={["right"]="h",
["left"]="h",
["up"]="v",
["down"]="v"}
return test[dir]
end
local function is_valid(dir)
return not (get_vh(dir) == get_vh(mem.dirname))
end
if event.type=="digiline" and event.channel=="name" then
name=event.msg
mem.name=name
end

if event.type=="digiline" and event.channel=="buttons" then
dir=mem.dirs[event.msg]
if not dir then
if event.msg=="middle" then
--[[mem.cursor={0,0}
digiline_send("screen", {"all",false})
digiline_send("screen", {mem.cursor,true})
mem.length=0
mem.dir={1,0}
mem.tail={{0,0}}
mem.dirname="left"
mem.food={math.random(0,mem.w-1), math.random(0,mem.h-1)}
digiline_send("screen", {mem.food,true})]]
reset()
end
return
end
if is_valid(event.msg) then
mem.dir=dir
mem.dirname=event.msg

end
end
local function equal_pos(p1,p2)
return (p1[1]..","..p1[2] == p2[1]..","..p2[2])
end
local function select_new_food_pos()
pos=random_pos()
if touching_tail(pos) then
while touching_tail(pos) do
pos=random_pos()
end
end
mem.food=pos
digiline_send("screen", {mem.food,true})

end
local function die()
mem.running=false
digiline_send("image_manager", "dead")--die
digiline_send("highscore", {mem.name,mem.length})
end
--main loop
if event.type=="interrupt" then
if (mem.cursor[1]+mem.dir[1]<0 or mem.cursor[1]+mem.dir[1]>mem.w-1) or (mem.cursor[2]+mem.dir[2]<0 or mem.cursor[2]+mem.dir[2]>mem.h-1) then
die()

return
end

--digiline_send("screen", {mem.cursor,false})
if #mem.tail-1>mem.length then
digiline_send("screen", {mem.tail[1],false})
table.remove(mem.tail,1)
end
mem.cursor={mem.cursor[1]+mem.dir[1],mem.cursor[2]+mem.dir[2]}
if touching_tail(mem.cursor) then
mem.running=false
die()
return
end
if equal_pos(mem.cursor, mem.food) then
mem.length=mem.length+1
select_new_food_pos()
end
digiline_send("screen", {mem.cursor,true})
--[[for i,j in ipairs(mem.tail) do
digiline_send("screen", {j,true})
end]]
digiline_send("screen", {mem.food,true})
table.insert(mem.tail, mem.cursor)
interrupt(1)
end





--[[test-program
if event.type=="program" then
mem.w=6
mem.h=6
mem.cursor={0,0}
digiline_send("screen", {"all",false})
digiline_send("screen", {mem.cursor,true})
mem.dirs={["up"]={0,1},
["down"]={0,-1},
["left"]={1,0},
["right"]={-1,0},}
end
if event.type=="digiline" and event.channel=="buttons" then
dir=mem.dirs[event.msg]
if not dir then
if event.msg=="middle" then
digiline_send("screen", {mem.cursor,false})
mem.cursor={0,0}
digiline_send("screen", {mem.cursor,true})
end
return
end
if (mem.cursor[1]+dir[1]<0 or mem.cursor[1]+dir[1]>mem.w-1) or (mem.cursor[2]+dir[2]<0 or mem.cursor[2]+dir[2]>mem.h-1) then return end
digiline_send("screen", {mem.cursor,false})
mem.cursor={mem.cursor[1]+dir[1],mem.cursor[2]+dir[2]}
digiline_send("screen", {mem.cursor,true})
end--]]

Mittlerer Controller:

if event.type=="program" then
mem.images={["404"]={},
["dead"]={{2,2}, {5,2}, {3,3}, {4,3}, {2,5}, {5,5}}, 
["clear"]={}}

end

if event.type == "digiline" and event.channel=="image_manager" then
digiline_send("screen", {"all",false})
image=mem.images[event.msg] or mem.images["404"]
for i,j in ipairs(image) do
digiline_send("screen",{j,true})
end
end

Oberer Controller:

if event.type=="program" then
mem.list={}
end
local function update()
digiline_send("display", "\n\n\n\n\n\n")
for i,j in pairs(mem.list) do
digiline_send("display", j[1]..": "..j[2])
end

end

if event.type=="digiline" and event.channel=="highscore" then
name=event.msg[1]
points=event.msg[2]
if #mem.list==0 then
table.insert(mem.list,{name,points})
elseif mem.list[#mem.list][2]<=points then
for i,j in ipairs(mem.list) do
if j[2]<=points then
table.insert(mem.list,i,{name,points})
break
end
end
if #mem.list > 6 then 
table.remove(mem.list,#mem.list)
end
elseif #mem.list<7 then
table.insert(mem.list,{name,points})
end
update()
end

Schalter für neues Spiel:

if event.type=="program" then
mem.list={}
end
local function update()
digiline_send("display", "\n\n\n\n\n\n")
for i,j in pairs(mem.list) do
digiline_send("display", j[1]..": "..j[2])
end

end

if event.type=="digiline" and event.channel=="highscore" then
name=event.msg[1]
points=event.msg[2]
if #mem.list==0 then
table.insert(mem.list,{name,points})
elseif mem.list[#mem.list][2]<=points then
for i,j in ipairs(mem.list) do
if j[2]<=points then
table.insert(mem.list,i,{name,points})
break
end
end
if #mem.list > 6 then 
table.remove(mem.list,#mem.list)
end
elseif #mem.list<7 then
table.insert(mem.list,{name,points})
end
update()
end

Schalter „nach links“:

if event.type=="on" and pin.c then
digiline_send("buttons", "left")
end

Jetzt anmelden: Großer Online-Fortbildungstag zu Minetest, Game-based-Learning, Coding/Robotik

Das Programm für den großen Fortbildungstag „explorandlearn“ am 15. Mai (Samstag) ist fertig und mit hochkarätigen Referent:innen besetzt. Der Termin ist günstig: Samstag nach Himmelfahrt mit einem schönen Auftakt am Freitagabend, wo man sich miteinander im Barcamp-Stil bekannt machen kann, indem man auf einen der Minetest-Server der Netzwerkpartner geht. Das Minetest-Bildungsnetzwerk ist beteiligt und hat viele Leute organisiert, die Einblick geben werden in die Möglichkeiten für Minetest für schulische und außerschulische Bildung.

Besonders freuen wir uns, dass Milan und dotti vom Illuna-Minetest-Projekt (https://illuna-minetest.tk) gewonnen werden konnten für eine Präsentation ihrer langjährigen Erfahrungen.

Außerdem sind dabei

Highlight der Veranstaltung wird die Keynote von Jane McGonigal sein. Ihr Beitrag unter dem Titel „Reality is Broken. Why Games Make Us Better and How They Can Change the World“ wird eine starke Lanze brechen für gute Spiele und ihr Potential für Bildung und Veränderung der Welt zum Besseren.

Werbematerialien

Wir freuen uns, wenn sich noch viele für diese tolle, vom Landesmedienzentrum Baden-Württemberg organisierte und kostenlose Online-Veranstaltung anmelden.

Die Info-Flyer als PDF zur Weitergabe an Bildungsmenschen und Schüler:innen:

Bilder