-- title: einhander -- author: pixelbath -- desc: one-handed -- script: lua -- TODO: -- configurable controls -- cannon: more animation when firing -- gun transition sprites -- enemy collisions -- ammo counting seed=12345 player={ x=20, y=50, vx=0, vy=0, speed=1.5, inv=0, show=1, fire=0, gun_down=0, gun_anim=0, gun_held=0, is_firing=0, big_gun_cooldown=0, } gunsprites={ 292, -- vulcan 294, -- cannon 296, -- spreader 298, -- wasp 300, -- grenade 302, -- hedgehog } gunnames={ {324, "V", "ULCAN"}, {325, "C", "ANNON"}, {326, "S", "PREADER"}, {327, "W", "ASP"}, {328, "G", "RENADE"}, {329, "H", "EDGEHOG"}, } vulcanMuzzleSprites={ 264, 266, 280 } shellParticles={} -- particles are just white pixels by default for i=1,15 do table.insert(shellParticles, {x=0,y=0,vx=0,vy=0,age=0,dieAt=0,color=12,idx=0,isPixel=true}) end particlePointer=1 -- points at the next particle to be spawned weaponBgSize=16--12 weaponBgTimer=0 weaponAmmo=3000 p_bullets = {} p_big_bullets = {} multiplier = 12 multiplier_sub = 0 multiplier_tick = 0 score = 25000 active_enemies={} t=0 math.randomseed(seed) -- create a mapping for darkening palette colors -- note: this is for the default sweetie16 palette drk={[0]=0,0,1,2,3,6,7,15,0,8,9,10,13,14,15,0} function drawParallelogram(x, y, w, h, skewpx, color) tri(x+skewpx, y, x+w, y+h, x, y+h, color) tri(x+skewpx, y, x+w, y+h, x+w+skewpx, y, color) end function spawnPixelParticle(x, y, vx, vy, age, dieAt, color) local p = shellParticles[particlePointer] p.x = x p.y = y p.vx = vx p.vy = vy p.age = age p.dieAt = dieAt p.color = color p.isPixel = true particlePointer = particlePointer + 1 if particlePointer > 15 then particlePointer = 1 end end function spawnSpriteParticle(x, y, vx, vy, age, dieAt, index) local p = shellParticles[particlePointer] p.x = x p.y = y p.vx = vx p.vy = vy p.age = age p.dieAt = dieAt p.idx = index p.isPixel = false particlePointer = particlePointer + 1 if particlePointer > 15 then particlePointer = 1 end end function spawnEnemySprite(x, y, age, type) local e = {} e.hp = 0 e.hp_shield = 0 e.x = x e.y = y e.age = age e.type = type if type == 1 then e.hp = 100 e.hp_shield = 50 end table.insert(active_enemies, e) end spawnEnemySprite(150, 50, 0, 1) function updateEnemies() for i=1,#active_enemies do local e = active_enemies[i] -- car - medium if e.type == 1 then end e.age = e.age + 1 end end function drawEnemies() for i=1,#active_enemies do local e = active_enemies[i] -- car - medium if e.type == 1 then -- shield spr(352, e.x, e.y, 0, 1, 0, 0, 2, 1) -- body spr(354, e.x + 6, e.y, 0, 1, 0, 0, 3, 1) end end end function drawPlayer() if (player.show) then -- arm if player.gun_anim > 0 then --spr(260, player.x+12, player.y+11, 0, 1, 0, 3, 2, 1) else if player.gun_down then spr(260, player.x+12, player.y+11, 0, 1, 0, 0, 2, 1) else spr(260, player.x+12, player.y-2, 0, 1, 2, 0, 2, 1) end end -- ship spr(256, player.x, player.y, 0, 1, 0, 0, 4, 2) end -- draw regular bullets for key,val in ipairs(p_bullets) do spr(262, val.x, val.y, 0) end -- draw big bullets for key,val in ipairs(p_big_bullets) do local spritenum = 0 if val.type == 2 then spritenum = 282 end if val.type == 3 then spritenum = 267 end spr(spritenum, val.x, val.y, 0) end -- custom routines depending on gun held if player.gun_held > 0 then local gunsprite = gunsprites[player.gun_held] local gunpos = player.y - 2 if player.gun_down then gunsprite = gunsprite + 16 gunpos = gunpos + 14 end if player.gun_anim > 0 then spr(gunsprite, player.x+3, gunpos, 0, 1, 0, 3, 2, 1) else spr(gunsprite, player.x+12, gunpos, 0, 1, 0, 0, 2, 1) end -- vulcan if player.gun_held == 1 then local flipfire = 0 local muzzleIdx = math.random(0,3) if math.random(1, 2) == 2 then flipfire = 2 end if player.fire == 0 then player.fire = 2 else player.fire = player.fire - 1 end -- not tracking individual bullets with vulcan -- begin dakka if player.is_firing > 0 then if muzzleIdx > 0 then if player.gun_down then spr(vulcanMuzzleSprites[muzzleIdx], player.x + 27, player.y + 14, 0, 1, flipfire, 0, 2, 1) else spr(vulcanMuzzleSprites[muzzleIdx], player.x + 28, player.y - 2, 0, 1, flipfire, 0, 2, 1) end end if t % 10 == 0 then local randFactor = math.random(10,100) local spawnOffsetY = 1 local lineStart = math.random(player.x//1+20, 260) if player.gun_down then spawnOffsetY = 18 -- vulcan tilts downward so we get to do trig! yay! lineStart = lineStart - player.x local angle = 8 local radius2 = lineStart+38 local c = math.cos(angle * math.pi / 180) local s = math.sin(angle * math.pi / 180) line(c * lineStart + player.x + 18, s * lineStart + player.y + 17, c * radius2 + player.x + 18, s * radius2 + player.y + 17, 14) else line(lineStart, player.y+1, lineStart+40, player.y+1, 14) end -- shells spawnPixelParticle(player.x+14, player.y+spawnOffsetY, -0.2, -0.6 + (randFactor / 100), 0, 50, 15) end end -- update shells with light gravity for i=1,#shellParticles do local p = shellParticles[i] p.vy = p.vy + 0.1 end end -- cannon if player.gun_held == 2 then if player.fire == 0 then player.fire = 30 else player.fire = player.fire - 1 end -- todo: move to update() for i=1, #p_big_bullets do if p_big_bullets[i].x < 250 then p_big_bullets[i].x = p_big_bullets[i].x + 10 end end end end for i=1,#shellParticles do local p = shellParticles[i] if p.age < p.dieAt then if p.isPixel then pix(p.x, p.y, p.color) else spr(p.idx, p.x, p.y) end end end if player.gun_anim > 0 then player.gun_anim = player.gun_anim - 1 end end function drawUI() -- weapon bg -- spr(322, 4, 114, 0, 1, 0, 0, 1, 2) -- rect(12, 114, 8, 16, 6) -- spr(323, 20, 114, 0, 1, 0, 0, 1, 2) drawParallelogram(6, 115, weaponBgSize, 12, 6, 6) -- selected weapon if player.gun_held > 0 then local lettersprite = gunnames[player.gun_held][1] local guntext = gunnames[player.gun_held][3] spr(lettersprite, 14, 118, 0, 1) print(guntext, 24, 122, 12, true, 1, true) print(weaponAmmo, 12, 129, 12, true, 1, true) end -- multiplier -- TODO: need to do multipliers over 10, so the X needs to move left when that happens spr(340, 164, 114, 0) --spr(340 + multiplier, 172, 113, 0) spr(330, 180, 114, 0, 1, 0, 0, 4, 1) spr(331, 212, 114, 0, 1, 0, 0, 3, 1) spr(334, 236, 114, 0, 1) if multiplier_sub > 0 then for i = 1, multiplier_sub do spr(335, 177 + (i * 6), 114, 0) end end -- score local scorestring = tostring(score) for i = 1, #scorestring do local char = scorestring:sub(i, i) local numsprite = 340 + tonumber(char) -- this is a hack because I ordered the numbers weirdly if char == "0" then numsprite = 350 end spr(numsprite, (230 - (8 * #scorestring)) + (i * 8), 123, 0) end end function drawWater(waterHeight) tm=time()/200 for x=0,239 do for y=waterHeight,135 do -- introduce some wobble ox=x+2*math.sin(tm+y) oy=waterHeight-(y-waterHeight)-1 oc=pix(ox,oy) -- darken reflected pixel pix(x,y,drk[oc]) end end end function drawDebug() -- print("p.gdown: " .. tostring(player.gun_down), 5, 5, 12, true, 1, true) -- print("spr: " .. tostring(vulcanMuzzleSprites[player.fire + 1]), 5, 13, 12, true, 1, true) end function update() player.vx = 0 player.vy = 0 if btn(0) then player.vy=-player.speed end if btn(1) then player.vy=player.speed end if btn(2) then player.vx=-player.speed end if btn(3) then player.vx=player.speed end -- slow down diagonal movements if player.vx * player.vy ~= 0 then player.vx = player.vx * 0.707 player.vy = player.vy * 0.707 end player.x = player.x + player.vx player.y = player.y + player.vy if player.x < 5 then player.x = 5 end if player.x > 220 then player.x = 220 end if player.y < 5 then player.y = 5 end if player.y > 128 then player.y = 128 end -- A: fire main gun if btn(4) then if player.fire == 0 then player.fire = 5 table.insert(p_bullets, {x=player.x+10, y=player.y+2}) else player.fire = player.fire - 1 end end -- B: fire accessory gun if btn(5) then if player.gun_held == 1 then player.is_firing = 1 end if player.gun_held == 2 then -- controlled by cooldown (or semi-auto) if player.is_firing == 1 then player.is_firing = 0 end if player.big_gun_cooldown == 0 then player.big_gun_cooldown = 30 player.is_firing = 1 else player.big_gun_cooldown = player.big_gun_cooldown - 1 player.is_firing = 0 end if player.is_firing == 1 then table.insert(p_big_bullets, {x=player.x+12, y=player.y+6, type=player.gun_held}) end end else player.big_gun_cooldown = 0 player.is_firing = 0 end -- X: switch arm if btnp(6) then player.gun_down = not player.gun_down player.gun_anim = 1 end -- Y: swap weapon (debug) if btnp(7) then player.gun_held = player.gun_held + 1 if player.gun_held > 6 then player.gun_held = 0 end end for key,val in ipairs(p_bullets) do p_bullets[key].x = p_bullets[key].x + 8 if val.x > 240 then table.remove(p_bullets, key) end end for key,val in ipairs(p_big_bullets) do p_big_bullets[key].x = p_big_bullets[key].x + 8 if val.x > 240 then table.remove(p_big_bullets, key) end end for i=1,#shellParticles do local p = shellParticles[i] p.x = p.x + p.vx p.y = p.y + p.vy p.age = p.age + 1 end t=t+1 end function TIC() update() cls(0) drawPlayer() drawEnemies() drawWater(120) drawUI() drawDebug() end -- -- 000:00ffffff00ffffff00ffffff00ffffff00ffffff00ffffff00ffffff00ffffff -- 001:ffffffeeffffffeeffffffeeffffffeeffffffeeffffffeeffffffeeffffffee -- 004:eee00000e0e00000efe00000f0f0fff0f0f0000000f000000000000000000000 -- 005:eee00000e0e00000efe00000f0f0fff0f0f0f0f000f000000000000000000000 -- 006:eee00000e0e00000efe00000f0f0fff0f0f0000000f000000000000000000000 -- 007:eee00000e0e00000efe00000f0f0fff0f0f0f0f000f000000000000000000000 -- 016:ffffffffffffffffffffffffffbbbffbffbbbffbffffffffffffffffffffffff -- 017:ffffffffffffffffffffffffbbffffffbbffffffffffffffffffffffffffffff -- 020:0000000000000000000000000099008800aa0088009a00880088000000000000 -- 021:000000000000000000000000009a00aa00aa00aa009900990088008800000000 -- 022:0000000000000000000000000099009900aa00a900aa00aa0088008800000000 -- 023:000000000000000000000000009a009a00aa009a009900990088008800000000 -- 033:ffffffffffffffffffffffffbbf888ffbbf888fbffffffffffffffffffffffff -- -- -- 000:04488a844488aaaa4889999a00000d99000000d90000000d0000000000000000 -- 001:48000000889aa000aa889aa09aaa899a99aaa884999aa8430d99a43f00d999ff -- 002:000000000000000000000000a00000004400000038ddc000f8998000ff88dbc0 -- 004:0d000000d9add0009999addd8122999900128889000890080000000000000000 -- 005:000000000000000000000000d000000080000000800000000000000000000000 -- 006:0000000000000000000000000000440044444cc0000044000000000000000000 -- 007:000000000000000000000000eddc0000fee00000000000000000000000000000 -- 008:00000000000000000cc40000ccccccccccccccc404cc00000000000000000000 -- 009:000000000000000000000000ccc4400000000000000000000000000000000000 -- 010:0000000000000000033000003333300033330000033000000000000000000000 -- 017:0009aaaa00088999000eee080000000000000000000000000000000000000000 -- 018:ffeeeddcaf0fffed880e65fe0000eed000000000000000000000000000000000 -- 019:00000000b0000000d00000000000000000000000000000000000000000000000 -- 020:0d000000d9add0009999addd8122999900128888000890000000000000000000 -- 021:0000000000000000000000009d00000098000000880000000000000000000000 -- 022:0300000034300000030000000000000000000000000000000000000000000000 -- 023:000000000000000000000000eddd0000feed0000000000000000000000000000 -- 024:0000000000000000033300004444333344444433033300000000000000000000 -- 025:0000000000000000000000000000000033000000000000000000000000000000 -- 026:0000000000000000000000000004444000444444000444400000000000000000 -- 032:0000000011101300211023003210340043104c0056705c006770650077707500 -- 036:00000000000000000edce000f999edddfffffeee000099dd0000fff000000000 -- 037:0000000000000000000000d0dddddd9deeeeeefe000000f00000000000000000 -- 038:00000000000000000000dddd0dd0ffe3defddeeed2eeeff9ff00feed00000ff0 -- 039:0000dde00ddee900ee9000003000000000000000d00000000000000000000000 -- 040:000000000000000001eeef00d1e77770d3766667c4d66666000000ee00000000 -- 041:00000000000000000000000077700750f565065077776e500077755000000000 -- 042:0000000000000000000c555c000b646b000b666b0009777900000ff000000000 -- 043:0000000000000000540000006300000063000000720000000000000000000000 -- 044:00000000000000000000edd600006ed600dd7ff600ee777700000fe000000000 -- 046:00000000000dd0dd000ee0ee000ee0ee000444440003fff30003333300000000 -- 048:88808a0098809a00a980ab00ba80bc00cdf0cc00def0dc00ef80ed00f880fd00 -- 052:000000000fedc0000f999e0000fffddd00009eee0000f9de0000fff000000000 -- 053:000000000000000000000000d0000000dddd000deeeeddd9000eeefd000000f0 -- 054:00000000000000000ddd099dd2e9dffefeeeeee90000fff00000feed00000000 -- 055:0000000000000000ddddd000eeeeeeee34000000000000000000000000000000 -- 056:00000000000000005577700e5e677776560565f7570077700000000000000000 -- 057:0000000000000000e00000006666d4c0666673d07777e1d00feee10000000000 -- 058:000000000000000000000ff0000c555c000b666b000b636b0009777900000000 -- 059:0000000000000000000000005400000062000000620000007200000000000000 -- 060:0000000000000000000dd000006665dd006ed6ee007ee600007eff0000000000 -- 062:000000000000000000444440004fff400033333000fe0fe000ed0ed000ee0ee0 -- 068:0c00000c0c00000c0cc000cc00c000c000cc0cc0000c0c00000ccc000000c000 -- 069:00ccccc00cc000c00c0000000c0000000c0000000c0000000cc000c000ccccc0 -- 070:00ccccc00cc000000c0000000ccccc0000000cc0000000c000000cc00ccccc00 -- 071:0c00000c0c00000c0c00c00c0c00c00c0c00c00c0c00c00c0cc0c0cc00ccccc0 -- 072:00ccccc00cc000c00c0000000c0000000c00ccc00c0000c00cc000c000ccccc0 -- 073:0c0000c00c0000c00c0000c00cccccc00c0000c00c0000c00c0000c00c0000c0 -- 074:00dddddd000dd0000000dd00000dd00000dd00000dd0000d0ddddddd00000000 -- 075:dddddddd0dd0000d00dd00000dd0000ddd0000ddd0000dd0dddddddd00000000 -- 076:ddddddddd0000dd0dd0000ddd0000dd00000dd00000dd000dddddddd00000000 -- 077:dddddddd000dd0000000dd00000dd00000dd00000dd0000ddddddddd00000000 -- 078:dd0000000dd0000000d000000dd00000dd000000d00000000000000000000000 -- 079:0000000000333300000333300033330003333000333300000000000000000000 -- 080:0000b000000aabb000a999aa0090ffe90000fffe00000ff00000000000000000 -- 081:000000000000000000000000ab000000e9ab0000fee9ab0000fee9a00000fee0 -- 084:000000000c000c0000c0c000000c000000c0c0000c000c000000000000000000 -- 085:00000000000ccc000000cc000000cc000000cc000000cc000000cc000000cc00 -- 086:00000000000ccc0000c00cc000000cc00000cc00000cc00000cc000000ccccc0 -- 087:00000000000ccc0000c00cc000000cc00000cc0000000cc000c00cc0000ccc00 -- 088:00000000000ccc0000cccc0000c0cc000cc0cc000c00cc000cccccc00000cc00 -- 089:0000000000ccccc000cc000000cccc0000000cc000000cc000c00cc0000ccc00 -- 090:00000000000ccc0000cc00c000cc000000cccc0000cc0cc000cc0cc0000ccc00 -- 091:0000000000ccccc000000cc000000cc00000cc000000cc00000cc000000cc000 -- 092:00000000000ccc0000cc0cc000cc0cc0000ccc0000cc0cc000cc0cc0000ccc00 -- 093:00000000000ccc0000cc0cc000cc0cc0000cccc000000cc000c00cc0000ccc00 -- 094:00000000000ccc0000cc0cc000cc0cc000cc0cc000cc0cc000cc0cc0000ccc00 -- 096:0000000000000000000000aa0000ae9900ae9998ae99998e944cc8889944cc88 -- 097:00000000aadddddaae999eaa9999dddd8889ffeeee9999f08888880088888000 -- 098:000000000000000000000000000aaa9900a9eded0a9ededdd888888800000000 -- 099:00000000000000cc00000bdbddd0bddeeeeddddfee9999998811222200000222 -- 100:0000000000000000000ddb00fffee000bfcfa000999999003333334022222224 -- -- -- 006:000000000112010110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -- 007:000000000101010110000000515161610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -- 008:000000000101111210000000715161410000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -- 009:000000000101010110000000417161610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -- 010:000000000101011210000000615161710000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -- 011:000000000101010110000000515171510000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -- 012:000000000101011210000000715161610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -- 013:000000000112010110000000616141710000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -- 014:000000000101010110000000715161710000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -- 015:000000000101010110000000515161710000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -- 016:000000000101120110000000714161410000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -- -- -- 000:00000000ffffffff00000000ffffffff -- 001:012345678acdeeffffeedca876543210 -- 002:0123456789abcdef0123456789abcdef -- 003:ff000000000000000ff0000000000000 -- 004:01234000000000000000000000000000 -- -- -- 000:01000101010201020101010f010e010e010f0101010201020101010f010e010e010f0101010201020101010f010e010e010f0101010201020101010f6020000000f9 -- 001:9400940094009400940094009400a400a400a400a400b400b400b400b400b400b400b400c400c400c400c400d400d400d400e400e400f400f400f400212000000000 -- 002:030f030e130d330c530b730a9309b309d308f308f308f308f308f308f308f308f308f308f308f308f308f308f308f308f308f308f308f308f308f308105000000000 -- 003:85009500a500b500c500d500e500f500f500f500f500f500f500f500f500f500f500f500f500f500f500f500f500f500f500f500f500f500f500f500502000000000 -- 004:6500750085009500a500b500c500d500e500f500f500f500f500f500f500f500f500f500f500f500f500f500f500f500f500f500f500f500f500f500572000000000 -- -- -- 000:40002200000000003000000050003a00000000003000000040002200000000003000000050003a000000000030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -- -- -- 000:1800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002e0000 -- -- -- 000:1a1c2c5d275db13e53ef7d57ffcd75a7f07038b76425717929366f3b5dc941a6f673eff7f4f4f494b0c2566c86333c57 --