From 32ea9f46cac11b21542e3fbd036a48d63b54dbb1 Mon Sep 17 00:00:00 2001 From: Julien Danjou Date: Tue, 14 Oct 2008 18:16:26 +0200 Subject: [PATCH] invaders: import Signed-off-by: Julien Danjou --- icons/invaders/bullet_enemy.png | Bin 0 -> 247 bytes icons/invaders/bullet_player.png | Bin 0 -> 247 bytes icons/invaders/enemy_1.png | Bin 0 -> 633 bytes icons/invaders/enemy_2.png | Bin 0 -> 739 bytes icons/invaders/enemy_3.png | Bin 0 -> 570 bytes icons/invaders/player.png | Bin 0 -> 661 bytes lib/invaders.lua.in | 500 +++++++++++++++++++++++++++++++ 7 files changed, 500 insertions(+) create mode 100644 icons/invaders/bullet_enemy.png create mode 100644 icons/invaders/bullet_player.png create mode 100644 icons/invaders/enemy_1.png create mode 100644 icons/invaders/enemy_2.png create mode 100644 icons/invaders/enemy_3.png create mode 100644 icons/invaders/player.png create mode 100644 lib/invaders.lua.in diff --git a/icons/invaders/bullet_enemy.png b/icons/invaders/bullet_enemy.png new file mode 100644 index 0000000000000000000000000000000000000000..41cb1d8703e4b16bdf04df2902c102984933552f GIT binary patch literal 247 zcmeAS@N?(olHy`uVBq!ia0vp^tU%1o!3HF^r@BuCQY^(zo*^7SP{WbZ0pxQQctjR6 zFt9HMVMYV}O-F%(k|nMYCBgY=CFO}lsSM@i<$9TU*~Q6;1*v-ZMd`EO*+>Bum3X>1 zhHzZ>J-acJi9x{OVtC|k$2QMY!3`pct+5W5Qd)Z+N=P2oJi^MNE%+zXZ$s6G_kF_8 zcN{%lA@*Hk-?7~hN7o7Mj_7=yQ_~k-*y)~gy!*xxf1P8!GsW&dc9wZ8^8WF~n%HAj n_q5LcuwGujzR><-z)yDLxv92i?3gQn_A_|8`njxgN@xNA3{+Un literal 0 HcmV?d00001 diff --git a/icons/invaders/bullet_player.png b/icons/invaders/bullet_player.png new file mode 100644 index 0000000000000000000000000000000000000000..340757476cb71f168984f24d504774b96927e8fa GIT binary patch literal 247 zcmeAS@N?(olHy`uVBq!ia0vp^tU%1o!3HF^r@BuCQY^(zo*^7SP{WbZ0pxQQctjR6 zFt9HMVMYV}O-F%(k|nMYCBgY=CFO}lsSM@i<$9TU*~Q6;1*v-ZMd`EO*+>Bum3X>1 zhHzX@{_+36J@euEwj2evgEs~2TsBB*?U0NNVCZ0Oh>$zOZsf=O(OIFa?b33`rvD3~ ziWh#dpOC;JAkJtgJ*AI_m=d%$@fGL?r`$ mnR|RN6!_1Q6tD4Dg2Bcr)z)d@j&nf!89ZJ6T-G@yGywog3s2Ah literal 0 HcmV?d00001 diff --git a/icons/invaders/enemy_1.png b/icons/invaders/enemy_1.png new file mode 100644 index 0000000000000000000000000000000000000000..0ed0929210016ccdbf95df0a3a237f97b3788d46 GIT binary patch literal 633 zcmV-<0*3vGP)qr#6nm}A{$W@ zg|Lv7kcBDPD4{HD#MU1mWHEL$_nvp(tZXp8LOj>BbBELHJ67GYT#4P39l7Av^$_1DimO#mxyfkp*Ej#J46= z+mT459QK*x(4|tU))>9W9LDJ^r&{&LZDVK#g4s*8F=|VKKNw>gFunsHMASi~uf0R) zlYa>#g+L^>F03!l|&g-m(M=z1Yz<^?#N0ba17(#pmv;9||4 z<2d#5B@+u^ykO4G4A&d;_p)y)r7+&;aw1I>%=9_o>#s?~)1hC4DJXsS9Ggn4+KplU z7PZ>Px+<@k@H2AiV6Sf~>oze9wYUyy5eMnf@f;*ZB5?MB~S2@e5Ee!AZ`!&Ucd TTm1jI00000NkvXXu0mjf&u$sX literal 0 HcmV?d00001 diff --git a/icons/invaders/enemy_2.png b/icons/invaders/enemy_2.png new file mode 100644 index 0000000000000000000000000000000000000000..28902dd590ce1d0b95e4375cf033304bf88570bf GIT binary patch literal 739 zcmV<90v!E`P)%Z4p`|Mb`T#iMNmGU_l2Ro{LkHn@x89c4_{a>3t`J2*p2psogM;j4X z4Yq>joKmT*QU^!6x|%&9_QQ3)a@{z5Ix9pw>p0j3R@E&K;E@n>{nM2nOL?f`TUI*o zA9Q!msFkCpfIcawe?p?ydCOXdeF2^o3}Zd^4Jh2|=$PKH07*}POG8q&VNa9j{E%%g z$_a7Slk&{4_NBZ4oI%q}U@z0IV~xyUOqcH|buwrL{^5!*<&h9?`2L5w1sGt44R`Xk zy@r!rp^BR&r4l5*0e=mffWM7@(KF2?{#{*ZRRMzDg3n-6s6{W?^o7zp1Fj(DeAf4g zyEp8*a{`{(Y=H9+Js0Xg0t|rbv7l6t2?dP%t>_Op&$g4Hwp6YpeowST_`8Exz32zU zqEahJ*jBWx7Fu)_u0;83z24phaEmAIz7QE=`aIWd8g!f`14^}embFy3lBze4ZNw}`-~FOZrdpnn+MTRqH4H%f@@l)qQ|y8N8uEF;M@o{a-s zge~FNyiyAbO0BH>PbN`IFmSLj#BcUFT}}MIp9(h51Rr(Z^#d5%A_P)9%(7fs@6j@JU`wCle2IF4L&9A~gveeGsG zVB2aE@guD(V^Ycy(v?ze0T)8FvtiP#a7q=BaPK(coU7e1Jl39B&zd~&FwL?Y%qu1L z+4wRrCXEXDT&&f(T8%KXQ?@M%NLsna!0A9=?o4Q4pb0)p4rcE(&pbJpiVW*ekq$J0@Fwn@E$``9!2PXm?nb+wG~ zEa1N#^UmZUvnSRMOdjZ#!|Vn40#bqY4Yyy)@ygBW|U@8Rz{t&Q?!Z|yd zc!o@a474FOgYcYue-#e7E7cR2IF6u~ zuoJNJ5PYXhXAIvjfK6q(V;J~bRM8R+x#NFLAbb7+C0;;~S0+3KCV6vg$t|`5t!dY7 zsA=n8DeK?VU8kl^cn|-RoRf3IBx9+OYeAFR$)B=;N2Rh4)uQ5jKr4Sp+z6#syC<{@ z(=1iFID*^WyKO$5zT*OKGoPC7DF{yich&Q7QaL||ZMsAbxr|{fHK;{RYBNC>*j2_~ zgZ<7P7uynkU_%!Atsyz&O3WrTL~EDYN$>Ia2U6A-^nF<#(t3q=vM$`^Jocd0J`>yk znoYZP9A#e4+hY6(e2aS3pXplxIOH;hvDBazHL1-6dy;Lm^n+Ux-&%#A;hJ!lO1@F? v?eVY!`~rqcgjpf9DkNwLcedmk7R{aCGd2o gamedata.field.x then + gb.x = gb.x + x + elseif x > 0 and gb.x < gamedata.field.x + gamedata.field.w - 30 then + gb.x = gb.x + x + end + + gamedata.player.base:geometry(gb) +end + +function player.fire() + if gamedata.ammo > 0 then + gamedata.ammo = gamedata.ammo - 1 + gamedata.field.status.text = gamedata.score.." | "..gamedata.ammo .. " " + local gb = gamedata.player.base:geometry() + shots.fire(gb.x + 9, gb.y - 10, "#00FF00") + end +end + +function shots.fire (x, y, color) + local s = wibox({ position = "floating", bg = color }) + s:geometry({ width = 4, height = 10, x = x, y = y }) + s.screen = 1 + + for i = 1, gamedata.ammo_max do + if not gamedata.shots[i] or gamedata.shots[i].screen == nil then + gamedata.shots[i] = s + break + end + end +end + +function shots.fire_enemy (x, y, color) + if gamedata.enemies.shots.fired < gamedata.enemies.shots.max then + gamedata.enemies.shots.fired = gamedata.enemies.shots.fired + 1 + local s = wibox({ position = "floating", bg = color }) + s:geometry({ width = 4, height = 10, x = x, y = y }) + s.screen = 1 + for i = 1, gamedata.enemies.shots.max do + if not gamedata.enemies.shots[i] or gamedata.enemies.shots[i].screen == nil then + gamedata.enemies.shots[i] = s + break + end + end + end +end + +function shots.handle() + if not gamedata.running then return false end + if gamedata.ammo == gamedata.ammo_max then return false end + + gamedata.ammo = gamedata.ammo_max + + for i = 1, gamedata.ammo_max do + local s = gamedata.shots[i] + if s and s.screen then + gamedata.ammo = gamedata.ammo - 1 + local g = s:geometry() + if g.y < gamedata.field.y + 15 then + s.screen = nil + gamedata.ammo = gamedata.ammo + 1 + else + g.y = g.y - 3 + s:geometry(g) + end + end + end + gamedata.field.status.text = gamedata.score.." | "..gamedata.ammo .. " " +end + + +function shots.handle_enemy () + if not gamedata.running then return false end + if gamedata.enemies.shots.fired == 0 then return false end + + for i = 1, gamedata.enemies.shots.max do + local s = gamedata.enemies.shots[i] + if s and s.screen then + local g = s:geometry() + if g.y > gamedata.field.y + gamedata.field.h - 15 then + s.screen = nil + gamedata.enemies.shots.fired = gamedata.enemies.shots.fired - 1 + else + g.y = g.y + 3 + s:geometry(g) + end + if game.collide(gamedata.player.base, s) then + game.over() + end + end + end +end + +function enemies.new (t) + e = wibox({ position = "floating", bg = "#12345600" }) + e:geometry({ height = gamedata.enemies.h, width = gamedata.enemies.w, + x = gamedata.field.x, + y = gamedata.field.y }) + e.screen = 1 + w = widget({ type = "imagebox", name = "enemy"..t }) + w.image = image("@AWESOME_ICON_PATH@/invaders/enemy_"..t..".png") + e:widgets({ w }) + return e +end + +function enemies.setup() + gamedata.enemies.data = { } + gamedata.enemies.h = 10 + gamedata.enemies.w = 20 + gamedata.enemies.rows = 4 + gamedata.enemies.x = 10 + gamedata.enemies.y = 5 + gamedata.enemies.dir = 1 + gamedata.enemies.count = gamedata.enemies.rows * 8 + if not gamedata.enemies.shots then gamedata.enemies.shots = { } end + gamedata.enemies.shots.max = 10 + gamedata.enemies.shots.fired = 0 + + gamedata.enemies.speed_count = 0 + + for y = 1, gamedata.enemies.rows do + gamedata.enemies.data[y] = { } + for x = 1, math.ceil((gamedata.enemies.count / gamedata.enemies.rows) + 1) do + gamedata.enemies.data[y][x] = enemies.new( math.random(1, 3) ) + end + end + + for i = 1, gamedata.ammo_max do + if gamedata.shots[i] then + gamedata.shots[i].screen = nil + end + end + + for i = 1, gamedata.enemies.shots.max do + if gamedata.enemies.shots[i] then + gamedata.enemies.shots[i].screen = nil + end + end +end + +function enemies.handle () + if not gamedata.running then return false end + + gamedata.enemies.number = 0 + + for y = 1, #gamedata.enemies.data do + for x = 1, #gamedata.enemies.data[y] do + local e = gamedata.enemies.data[y][x] + if e.screen then + local g = e:geometry() + gamedata.enemies.number = gamedata.enemies.number + 1 + if gamedata.enemies.speed_count == (gamedata.enemies.speed - 1) then + g.y = math.floor(gamedata.field.y + gamedata.enemies.y + ((y - 1) * gamedata.enemies.h * 2)) + g.x = math.floor(gamedata.field.x + gamedata.enemies.x + ((x - 1) * gamedata.enemies.w * 2)) + e:geometry(g) + if game.collide(gamedata.player.base, e) or g.y > gamedata.field.y + gamedata.field.h - 20 then + game.over() + end + end + if gamedata.ammo < gamedata.ammo_max then + for i = 1, #gamedata.shots do + local s = gamedata.shots[i] + if s and s.screen and game.collide(e, s) then + gamedata.enemies.number = gamedata.enemies.number - 1 + e.screen = nil + s.screen = nil + + gamedata.score = gamedata.score + 10 + gamedata.field.status.text = gamedata.score.." | "..gamedata.ammo.." " + break + end + end + end + end + end + + local x = math.random(1, gamedata.enemies.count / gamedata.enemies.rows) + if gamedata.enemies.speed_count == (gamedata.enemies.speed - 1) + and math.random(0, 150) <= 1 + and gamedata.enemies.data[y][x].screen then + shots.fire_enemy(math.floor(gamedata.field.x + gamedata.enemies.x + ((x - 1) * gamedata.enemies.w)), + gamedata.field.y + gamedata.enemies.y + gamedata.enemies.h, + "#FF0000") + end + end + + if gamedata.enemies.number == 0 then + enemies.setup() + if gamedata.enemies.speed > 0 then gamedata.enemies.speed = gamedata.enemies.speed - 1 end + return false + end + + gamedata.enemies.speed_count = gamedata.enemies.speed_count + 1 + if gamedata.enemies.speed_count < gamedata.enemies.speed then return false end + gamedata.enemies.speed_count = 0 + gamedata.enemies.x = gamedata.enemies.x + math.floor((gamedata.enemies.w * gamedata.enemies.dir) / 4) + if gamedata.enemies.x > gamedata.field.w - (2 * gamedata.enemies.w * (gamedata.enemies.count / gamedata.enemies.rows + 1)) - 10 + or gamedata.enemies.x <= 10 then + gamedata.enemies.y = gamedata.enemies.y + gamedata.enemies.h + gamedata.enemies.dir = gamedata.enemies.dir * (-1) + end +end + +function keyhandler(mod, key) + if gamedata.highscore.getkeys then + if key:len() == 1 and gamedata.name:len() < 20 then + gamedata.name = gamedata.name .. key + elseif key == "BackSpace" then + gamedata.name = gamedata.name:sub(1, gamedata.name:len() - 1) + elseif key == "Return" then + gamedata.highscore.window.screen = nil + game.highscore_add(gamedata.score, gamedata.name) + game.highscore_show() + gamedata.highscore.getkeys = false + end + gamedata.namebox.text = " Name: " .. gamedata.name .. "|" + else + if key == "Left" then + player.move(-10) + elseif key == "Right" then + player.move(10) + elseif key == "q" then + game.quit() + return false + elseif key == " " then + player.fire() + elseif key == "s" then + awful.util.spawn("import -window root ~/.cache/awesome/invaders-"..os.time()..".png") + end + end + return true +end + +function game.collide(o1, o2) + g1 = o1:geometry() + g2 = o2:geometry() + + --check if o2 is inside o1 + if g2.x >= g1.x and g2.x <= g1.x + g1.width + and g2.y >= g1.y and g2.y <= g1.y + g1.height then + return true + end + + return false +end + +function game.over () + gamedata.running = false + game.highscore(gamedata.score) +end + +function game.quit() + gamedata.running = false + + if gamedata.highscore.window then + gamedata.highscore.window.screen = nil + gamedata.highscore.window:widgets({ }) + end + + gamedata.player.base.screen = nil + gamedata.player.base:widgets({ }) + gamedata.player.base = nil + + gamedata.field.north.screen = nil + gamedata.field.north = nil + + gamedata.field.south.screen = nil + gamedata.field.south = nil + + gamedata.field.west.screen = nil + gamedata.field.west = nil + + gamedata.field.east.screen = nil + gamedata.field.east = nil + + for y = 1, #gamedata.enemies.data do + for x = 1, #gamedata.enemies.data[y] do + gamedata.enemies.data[y][x].screen = nil + gamedata.enemies.data[y][x]:widgets({ }) + end + end + + for i = 1, gamedata.ammo_max do + if gamedata.shots[i] then gamedata.shots[i].screen = nil end + end + + for i = 1, gamedata.enemies.shots.max do + if gamedata.enemies.shots[i] then gamedata.enemies.shots[i].screen = nil end + end +end + +function game.highscore_show () + gamedata.highscore.window:geometry({ height = 140, width = 200, + x = gamedata.field.x + math.floor(gamedata.field.w / 2) - 100, + y = gamedata.field.y + math.floor(gamedata.field.h / 2) - 55 }) + gamedata.highscore.window.screen = 1 + + gamedata.highscore.table = widget({ type = "textbox", name = "highscore" }) + gamedata.highscore.window:widgets({ gamedata.highscore.table }) + + gamedata.highscore.table.text = " Highscores:\n" + + for i = 1, 5 do + gamedata.highscore.table.text = gamedata.highscore.table.text .. "\n\t" .. gamedata.highscore[i] + end + + gamedata.highscore.table.text = gamedata.highscore.table.text .. "\n\n Press Q to quit" + + local fh = io.open(os.getenv("HOME") .. "/.cache/awesome/highscore_invaders","w") + if not fh then + return false + end + + for i = 1, 5 do + fh:write(gamedata.highscore[i].."\n") + end + + fh:close() +end + +function game.highscore_add (score, name) + local t = gamedata.highscore + + for i = 5, 1, -1 do + if tonumber(t[i]:match("(%d+) ")) <= score then + if t[i+1] then t[i+1] = t[i] end + t[i] = score .. " " .. name + end + end + + gamedata.highscore = t +end + +function game.highscore (score) + local fh = io.open(os.getenv("HOME").."/.cache/awesome/highscore_invaders", "r") + if fh then + for i = 1, 5 do + gamedata.highscore[i] = fh:read("*line") + end + fh:close() + else + for i = 1, 5 do + gamedata.highscore[i] = ((6-i)*20).." foo" + end + end + + local newentry = false + for i = 1, 5 do + local s = tonumber(gamedata.highscore[i]:match("(%d+) .*")) + if s <= score then newentry = true end + end + + gamedata.highscore.window = wibox({ position = "floating" }) + gamedata.highscore.window:geometry({ height = 20, width = 300, + x = gamedata.field.x + math.floor(gamedata.field.w / 2) - 150, + y = gamedata.field.y + math.floor(gamedata.field.h / 2) }) + gamedata.highscore.window.screen = 1 + + gamedata.namebox = widget({ type = "textbox", name = "foobar" }) + gamedata.namebox.text = " Name: |" + gamedata.highscore.window:widgets({ gamedata.namebox }) + + if newentry then + gamedata.name = "" + gamedata.highscore.getkeys = true + else + game.highscore_show() + end +end + +function run() + gamedata.running = true + gamedata.screen = 1 + gamedata.ammo_max = 10 + gamedata.score = 0 + gamedata.name = "" + gamedata.ammo = gamedata.ammo_max + + gamedata.player = player.new() + + + gamedata.field.north = wibox({ position = "floating", bg = "#333333" }) + gamedata.field.north:geometry({ width = gamedata.field.w + 10, + height = 15, + x = gamedata.field.x - 5, + y = gamedata.field.y - 15 }) + gamedata.field.north.screen = gamedata.screen + + gamedata.field.status = widget({ type = "textbox", name = "status", align = "right" }) + gamedata.field.status.text = gamedata.score.." | "..gamedata.ammo .. " " + + gamedata.field.caption = widget({ type = "textbox", name = "caption", align = "left" }) + gamedata.field.caption.text = " SpaceInvaders for Awesome 3" + + gamedata.field.north:widgets({ gamedata.field.caption, gamedata.field.status }) + + gamedata.field.south = wibox({ position = "floating", bg = "#333333" }) + gamedata.field.south:geometry({ width = gamedata.field.w, height = 5, + x = gamedata.field.x, + y = gamedata.field.y + gamedata.field.h - 5 }) + gamedata.field.south.screen = gamedata.screen + + gamedata.field.west = wibox({ position = "floating", bg = "#333333" }) + gamedata.field.west:geometry({ width = 5, + height = gamedata.field.h, + x = gamedata.field.x - 5, + y = gamedata.field.y }) + gamedata.field.west.screen = gamedata.screen + + gamedata.field.east = wibox({ position = "floating", bg = "#333333" }) + gamedata.field.east:geometry({ width = 5, + height = gamedata.field.h, + x = gamedata.field.x + gamedata.field.w, + y = gamedata.field.y }) + gamedata.field.east.screen = gamedata.screen + + gamedata.enemies.speed = 5 + + enemies.setup() + + keygrabber.run(keyhandler) +end + +awful.hooks.timer.register(0.03, shots.handle) +awful.hooks.timer.register(0.03, shots.handle_enemy) +awful.hooks.timer.register(0.01, enemies.handle)