game
Description
A collection of all my ComputerCraft programs and the APIs they use. This is mostly just to get them the fuck off of pastebin, and also to ensure that API owners don't change things to break my precious programs...!
Installation
Copy one of these commands into your ComputerCraft terminal:
wget:
wget https://raw.githubusercontent.com/LDDestroier/CC/master/platform-test/game.lua gameArchive:
wget https://cc.shobie.xyz/cc/get/gh-LDDestroier-CC-platform-test-game game
Quick Install:
wget https://cc.shobie.xyz/cc/get/gh-LDDestroier-CC-platform-test-game game
Usage
Run: game
Tags
Source
View Original SourceCode Preview
local game = {}
game.path = fs.combine(fs.getDir(shell.getRunningProgram()),"data")
game.apiPath = fs.combine(game.path, "api")
game.spritePath = fs.combine(game.path, "sprites")
game.mapPath = fs.combine(game.path, "maps")
game.imagePath = fs.combine(game.path, "image")
game.configPath = fs.combine(game.path, "config.cfg")
local scr_x, scr_y = term.getSize()
local mapname = "testmap"
local scrollX = 0
local scrollY = 0
local killY = 100
local keysDown = {}
local tsv = function(visible)
if term.current().setVisible then
term.current().setVisible(visible)
end
end
local getAPI = function(apiName, apiPath, apiURL, doDoFile)
apiPath = fs.combine(game.apiPath, apiPath)
if not fs.exists(apiPath) then
write("Getting " .. apiName .. "...")
local prog = http.get(apiURL)
if prog then
print("success!")
local file = fs.open(apiPath, "w")
file.write(prog.readAll())
file.close()
else
error("fail!")
end
end
if doDoFile then
_ENV[fs.getName(apiPath)] = dofile(apiPath)
else
os.loadAPI(apiPath)
end
end
getAPI("NFT Extra", "nfte", "https://github.com/LDDestroier/NFT-Extra/raw/master/nfte", false)
-- load sprites from sprite folder
-- sprites are separated into "sets", but the only one here is "megaman" so whatever
local sprites, maps = {}, {}
for k, set in pairs(fs.list(game.spritePath)) do
sprites[set] = {}
for num, name in pairs(fs.list(fs.combine(game.spritePath, set))) do
sprites[set][name:gsub(".nft", "")] = nfte.loadImage(fs.combine(game.spritePath, set .. "/" .. name))
print("Loaded sprite " .. name:gsub(".nft",""))
end
end
for num, name in pairs(fs.list(game.mapPath)) do
maps[name:gsub(".nft", "")] = nfte.loadImage(fs.combine(game.mapPath, name))
print("Loaded map " .. name:gsub(".nft",""))
end
local projectiles = {}
local players = {}
local newPlayer = function(name, spriteset, x, y)
return {
name = name, -- player name
spriteset = spriteset, -- set of sprites to use
sprite = "stand", -- current sprite
direction = 1, -- 1 is right, -1 is left
xsize = 10, -- hitbox x size
ysize = 8, -- hitbox y size
x = x, -- x position
y = y, -- y position
xadj = 0, -- adjust x for good looks
yadj = 0, -- adjust y for good looks
xvel = 0, -- x velocity
yvel = 0, -- y velocity
maxVelocity = 8, -- highest posible speed in any direction
jumpHeight = 2, -- height of jump
jumpAssist = 0.5, -- assists jump while in air
moveSpeed = 2, -- speed of walking
gravity = 0.75, -- force of gravity
slideSpeed = 4, -- speed of sliding
grounded = false, -- is on solid ground
shots = 0, -- how many shots onscreen
maxShots = 3, -- maximum shots onscreen
lemonSpeed = 3, -- speed of megabuster shots
chargeLevel = 0, -- current charged buster level
cycle = { -- used for animation cycles
run = 0, -- used for run sprite
shoot = 0, -- determines duration of shoot sprite
shootHold = 0, -- forces user to release then push shoot
stand = 0, -- used for high-octane eye blinking action
slide = 0, -- used to limit slide length
jump = 0, -- used to prevent auto-bunnyhopping
shootCharge = 0, -- records how charged your megabuster is
ouch = 0, -- records hitstun
iddqd = 0 -- records invincibility frames
},
chargeDiscolor = { -- swaps colors during buster charging
[0] = {{}},
[1] = { -- charge level one
{
["b"] = "a"
},
{
["b"] = "b"
}
},
[2] = { -- woAH charge level two
{
--["f"] = "b",
["b"] = "3",
["3"] = "f"
},
{
--["f"] = "3",
["3"] = "b",
["b"] = "f"
},
{
--["f"] = "3",
["3"] = "b",
["b"] = "8"
}
}
},
control = { -- inputs
up = false, -- move up ladders
down = false, -- move down ladders, or slide
left = false, -- point and walk left
right = false, -- point and walk right
jump = false, -- jump, or slide
shoot = false -- fire your weapon
}
}
end
local deriveControls = function(keyList)
return {
up = keyList[keys.up],
down = keyList[keys.down],
left = keyList[keys.left],
right = keyList[keys.right],
jump = keyList[keys.x],
shoot = keyList[keys.z]
}
end
-- main colision function
local isSolid = function(x, y)
x = math.floor(x)
y = math.floor(y)
if (not maps[mapname][1][y]) or (x < 1) then
return false
else
if (maps[mapname][1][y]:sub(x,x) == " " or
maps[mapname][1][y]:sub(x,x) == "") and
(maps[mapname][3][y]:sub(x,x) == " " or
maps[mapname][3][y]:sub(x,x) == "") then
return false
else
return true
end
end
end
local isPlayerTouchingSolid = function(player, xmod, ymod, ycutoff)
for y = player.y + (ycutoff or 0), player.ysize + player.y - 1 do
for x = player.x, player.xsize + player.x - 1 do
if isSolid(x + (xmod or 0), y + (ymod or 0)) then
return "map"
end
end
end
return false
end
you = 1
players[you] = newPlayer("LDD", "megaman", 40, 8)
local movePlayer = function(player, x, y)
i = player.yvel / math.abs(player.yvel)
for y = 1, math.abs(player.yvel) do
if isPlayerTouchingSolid(player, 0, -i, (player.cycle.slide > 0 and 2 or 0)) then
if player.yvel < 0 then
player.grounded = true
end
player.yvel = 0
break
else
player.y = player.y - i
player.grounded = false
end
end
i = player.xvel / math.abs(player.xvel)
for x = 1, math.abs(player.xvel) do
if isPlayerTouchingSolid(player, i, 0, (player.cycle.slide > 0 and 2 or 0)) then
if player.grounded and not isPlayerTouchingSolid(player, i, -1) then -- upward slope detection
player.y = player.y - 1
player.x = player.x + i
grounded = true
else
player.xvel = 0
break
end
else
player.x = player.x + i
end
end
end
-- types of projectiles
local bullet = {
lemon = {
damage = 1,
element = "neutral",
sprites = {
sprites["megaman"]["buster1"]
},
},
lemon2 = {
damage = 1,
element = "neutral",
sprites = {
sprites["megaman"]["buster2-1"],
sprites["megaman"]["buster2-2"]
}
},
lemon3 = {
damage = 4,
element = "neutral",
sprites = {
sprites["megaman"]["buster3-1"],
sprites["megaman"]["buster3-2"],
sprites["megaman"]["buster3-3"],
sprites["megaman"]["buster3-4"],
}
}
}
local spawnProjectile = function(boolit, owner, x, y, xvel, yvel)
projectiles[#projectiles+1] = {
owner = owner,
bullet = boolit,
x = x,
y = y,
xvel = xvel,
yvel = yvel,
direction = xvel / math.abs(xvel),
life = 32,
cycle = 0,
phaze = false,
}
end
local moveTick = function()
local i
for num, player in pairs(players) do
-- falling
player.yvel = player.yvel - player.gravity
-- jumping
if player.control.jump then
if player.grounded then
if player.cycle.jump == 0 then
if player.control.down and player.cycle.slide == 0 then
player.cycle.slide = 6
elseif not isPlayerTouchingSolid(player, 0, -1, 0) then
player.yvel = player.jumpHeight
player.cycle.slide = 0
player.grounded = false
end
end
player.cycle.jump = 1
end
if player.yvel > 0 and not player.grounded then
player.yvel = player.yvel + player.jumpAssist
end
else
player.cycle.jump = 0
end
-- walking
if player.control.right then
player.direction = 1
player.xvel = player.moveSpeed
elseif player.control.left then
player.direction = -1
player.xvel = -player.moveSpeed
else
player.xvel = 0
end
if player.cycle.slide > 0 then
player.xvel = player.direction * player.slideSpeed
end
-- shooting
if player.control.shoot then
if player.cycle.shootHold == 0 then
if player.shots < player.maxShots and player.cycle.slide == 0 then
spawnProjectile(
bullet.lemon,
player,
player.x + player.xsize * player.direction,
player.y + 2,
player.lemonSpeed * player.direction,
0
)
player.cycle.shoot = 5
player.shots = player.shots + 1
end
player.cycle.shootHold = 1
end
if player.cycle.shootHold == 1 then
player.cycle.shootCharge = player.cycle.shootCharge + 1
if player.cycle.shootCharge < 16 then
player.chargeLevel = 0
elseif player.cycle.shootCharge < 32 then
player.chargeLevel = 1
else
player.chargeLevel = 2
end
end
else
player.cycle.shootHold = 0
if player.shots < player.maxShots and player.cycle.slide == 0 then
if player.cycle.shootCharge > 16 then
if player.cycle.shootCharge >= 32 then
spawnProjectile(
bullet.lemon3,
player,
player.x + math.max(0, player.direction * player.xsize),
player.y,
player.lemonSpeed * player.direction,
0
)
else
spawnProjectile(
bullet.lemon2,
player,
player.x + math.max(0, player.direction * player.xsize),
player.y + 1,
player.lemonSpeed * player.direction,
0
)
end
player.shots = player.shots + 1
player.cycle.shoot = 5
end
end
player.cycle.shootCharge = 0
player.chargeLevel = 0
end
-- movement
if player.xvel > 0 then
player.xvel = math.min(player.xvel, player.maxVelocity)
else
player.xvel = math.max(player.xvel, -player.maxVelocity)
end
if player.yvel > 0 then
player.yvel = math.min(player.yvel, player.maxVelocity)
else
player.yvel = math.max(player.yvel, -player.maxVelocity)
end
if player.y > killY then
player.x = 40
player.y = -80
player.xvel = 0
end
movePlayer(player, xvel, yvel)
scrollX = player.x - math.floor(scr_x / 2) + math.floor(player.xsize / 2)
scrollY = player.y - math.floor(scr_y / 2) + math.floor(player.ysize / 2)
-- projectile management
for i = #projectiles, 1, -1 do
projectiles[i].x = projectiles[i].x + projectiles[i].xvel
projectiles[i].y = projectiles[i].y + projectiles[i].yvel
projectiles[i].cycle = projectiles[i].cycle + 1
projectiles[i].life = projectiles[i].life - 1
if projectiles[i].life <= 0 then
table.remove(projectiles, i)
player.shots = player.shots - 1
end
end
end
end
local render = function()
tsv(false)
term.clear()
nfte.drawImage(maps[mapname], -scrollX + 1, -scrollY + 1)
for num,player in pairs(players) do
term.setCursorPos(1,num)
print("(" .. player.x .. ", " .. player.y .. ", " .. tostring(player.shots) .. ")")
if player.direction == -1 then
nfte.drawImageTransparent(
nfte.colorSwap(
nfte.flipX(
sprites[player.spriteset][player.sprite]
),
player.chargeDiscolor[player.chargeLevel][
(math.floor(player.cycle.shootCharge / 2) % #player.chargeDiscolor[player.chargeLevel]) + 1
]
),
player.x - scrollX + player.xadj,
player.y - scrollY + player.yadj
)
else
nfte.drawImageTransparent(
nfte.colorSwap(
sprites[player.spriteset][player.sprite],
player.chargeDiscolor[player.chargeLevel][
(math.floor(player.cycle.shootCharge / 2) % #player.chargeDiscolor[player.chargeLevel]) + 1
]
),
player.x - scrollX,
player.y - scrollY
)
end
end
for num,p in pairs(projectiles) do
if p.direction == -1 then
nfte.drawImageTransparent(
nfte.flipX(p.bullet.sprites[(p.cycle % #p.bullet.sprites) + 1]),
p.x - scrollX,
p.y - scrollY
)
else
nfte.drawImageTransparent(
p.bullet.sprites[(p.cycle % #p.bullet.sprites) + 1],
p.x - scrollX,
p.y - scrollY
)
end
end
tsv(true)
end
-- determines what sprite a player uses
local determineSprite = function(player)
local output
player.xadj = 0
player.yadj = 0
if player.grounded then
if player.cycle.slide > 0 then
player.cycle.slide = math.max(player.cycle.slide - 1, isPlayerTouchingSolid(player, 0, 0, 0) and 1 or 0)
output = "slide"
else
if player.xvel == 0 then
player.cycle.run = -1
player.cycle.stand = (player.cycle.stand + 1) % 40
if player.cycle.shoot > 0 then
output = "shoot"
if player.direction == -1 then
player.xadj = -5
end
else
output = player.cycle.stand == 39 and "stand2" or "stand1"
end
else
if player.cycle.run == -1 and player.cycle.shoot == 0 then
player.cycle.run = 0
output = "walk0"
else
player.cycle.run = (player.cycle.run + 0.35) % 4
if player.cycle.shoot > 0 then
output = "walkshoot" .. (math.floor(player.cycle.run) + 1)
else
output = "walk" .. (math.floor(player.cycle.run) + 1)
end
end
end
end
else
player.cycle.slide = isPlayerTouchingSolid(player, 0, 0, 0) and 1 or 0
if player.cycle.shoot > 0 then
output = "jumpshoot"
if player.direction == -1 then
player.xadj = -1
end
else
output = "jump"
end
end
player.cycle.shoot = math.max(player.cycle.shoot - 1, 0)
return output
end
local getInput = function()
local evt
while true do
evt = {os.pullEvent()}
if evt[1] == "key" then
keysDown[evt[2]] = true
elseif evt[1] == "key_up" then
keysDown[evt[2]] = false
end
end
end
local main = function()
while true do
players[you].control = deriveControls(keysDown)
moveTick()
players[you].sprite = determineSprite(players[you])
render()
if keysDown[keys.q] then
return
end
sleep(0.05)
end
end
parallel.waitForAny(getInput, main)
term.setCursorPos(1, scr_y)
term.clearLine()