mirror of
https://gitlab.com/MaddoScientisto/cirnofarm.git
synced 2026-06-01 11:15:34 +00:00
374 lines
9 KiB
Lua
374 lines
9 KiB
Lua
--cd("/cirnofarm/src")
|
|
--include("/cirnofarm/src/cirno.lua")
|
|
|
|
function make_path(name)
|
|
local base_path = "/cirnofarm/src/" -- Change this when releasing
|
|
return base_path .. name
|
|
end
|
|
|
|
local _modules = {}
|
|
|
|
function loadfile (filename)
|
|
local src = fetch(filename)
|
|
|
|
if (type(src) ~= "string") then
|
|
notify("could not include "..filename)
|
|
stop()
|
|
return
|
|
end
|
|
|
|
-- https://www.lua.org/manual/5.4/manual.html#pdf-load
|
|
-- chunk name (for error reporting), mode ("t" for text only -- no binary chunk loading), _ENV upvalue
|
|
-- @ is a special character that tells debugger the string is a filename
|
|
local func,err = load(src, "@"..filename, "t", _ENV)
|
|
-- syntax error while loading
|
|
if (not func) then
|
|
send_message(3, {event="report_error", content = "*syntax error"})
|
|
send_message(3, {event="report_error", content = tostr(err)})
|
|
|
|
stop()
|
|
return
|
|
end
|
|
return func
|
|
end
|
|
|
|
function require(name)
|
|
local already_imported = _modules[name]
|
|
if already_imported ~= nil then
|
|
return already_imported
|
|
end
|
|
|
|
local filename = fullpath(name:gsub ('%.', '/') ..'.lua')
|
|
|
|
local func = loadfile (filename)
|
|
|
|
local module = func(name)
|
|
_modules[name]=module
|
|
|
|
return module
|
|
end
|
|
|
|
--local strawberry = require(make_path("strawberry"))
|
|
--strawberry.func()
|
|
|
|
local Cirno = require(make_path("cirno"))
|
|
local mouse_debug = require(make_path("mouse_debug"))
|
|
local map_manager = require(make_path("map"))
|
|
local weapons_manager = require(make_path("weapons"))
|
|
local Barrel = require(make_path("barrel"))
|
|
local Strawberry = require(make_path("strawberry"))
|
|
local Box = require(make_path("box"))
|
|
local NPC = require(make_path("npc"))
|
|
|
|
include(make_path("pgui" .. ".lua"))
|
|
|
|
particles_list = {
|
|
BLINK={
|
|
life=4,
|
|
spriteIndex=81
|
|
},
|
|
EXPLOSION={
|
|
life=8,
|
|
spriteIndex=83
|
|
}
|
|
}
|
|
|
|
bullets_list = {
|
|
BASIC={
|
|
spriteIndex=80,
|
|
damage=1,
|
|
speed=2,
|
|
life=100,
|
|
radius=4,
|
|
particle=particles_list.BLINK
|
|
}
|
|
}
|
|
|
|
weapons_list = {
|
|
ICE_BLASTER={
|
|
name = "Ice Blaster",
|
|
rate_of_fire = 8,
|
|
bullet=bullets_list.BASIC,
|
|
spriteIndex=104,
|
|
--shoot=function(self,x,y,dir_x,dir_y)
|
|
-- create_bullet(self.bullet, x, y, dir_x, dir_y)
|
|
--end
|
|
},
|
|
SPAGHETTI={
|
|
name = "Spaghetti",
|
|
rate_of_fire = 80,
|
|
bullet=bullets_list.BASIC,
|
|
spriteIndex=105,
|
|
}
|
|
}
|
|
|
|
LAYERS = {
|
|
{index=4, name="background", render=true, render_objects=false, spawn_objects=false},
|
|
{index=3, name="solid", render=true, render_objects=true, spawn_objects=false},
|
|
{index=2, name="foreground", render=true, render_objects=false, spawn_objects=false},
|
|
{index=1, name="objects", render=false, render_objects=false, spawn_objects=true}
|
|
}
|
|
|
|
actors_db = {
|
|
{name="teleporter",sprite=88,actor=nil},
|
|
{name="barrel",sprite=3,actor=Barrel},
|
|
{name="strawberry",sprite=72,actor=Strawberry},
|
|
{name="player",sprite=65,actor=nil},
|
|
{name="box",sprite=4,actor=Box},
|
|
{name="alarm",sprite=19,actor=nil},
|
|
{name="fan",sprite=16,actor=nil},
|
|
{name="NPC",sprite=69,actor=NPC}
|
|
}
|
|
|
|
|
|
|
|
tile_width = 16
|
|
tile_height = 16
|
|
|
|
function _init()
|
|
spawn_objects()
|
|
cirnoInstance = Cirno.init()
|
|
add(actors,cirnoInstance)
|
|
|
|
|
|
slidervalue = 10
|
|
end
|
|
|
|
function _update()
|
|
--cirno.update()
|
|
pgui:refresh()
|
|
|
|
weapons_manager.update()
|
|
|
|
for a in all(actors) do
|
|
a:update()
|
|
end
|
|
|
|
for b in all(bullets) do
|
|
b:update()
|
|
end
|
|
|
|
for p in all(particles) do
|
|
p:update()
|
|
end
|
|
|
|
check_collisions()
|
|
|
|
--slidervalue = pgui:component("hslider",{pos=vec(190,20),value=slidervalue})
|
|
|
|
pgui:component("vstack",{stroke=true,pos=vec(0,0),color={0,18,12,0,7,6},height=0,margin=3,gap=3,contents={
|
|
{"text_box",{text=string.format("x: %.2f y: %.2f", cirnoInstance.x, cirnoInstance.y),margin=2,stroke=true,active=false,hover=false},color={0,18,12,0,7,6}},
|
|
{"text_box",{text=string.format("mx: %.2f my: %.2f", cirnoInstance.move_x, cirnoInstance.move_y),margin=2,stroke=true,active=false,hover=false}},
|
|
{"text_box",{text=string.format("Actors: %d", count(actors)),margin=2,stroke=true,active=false,hover=false}},
|
|
{"text_box",{text=string.format("%.4f %dfps",stat(1),stat(7)),margin=2,stroke=true,active=false,hover=false}},
|
|
{"text_box",{text=string.format("Bullets: %d", count(bullets)),margin=2,stroke=true,active=false,hover=false}},
|
|
{"text_box",{text=string.format("Particles: %d", count(particles)),margin=2,stroke=true,active=false,hover=false}},
|
|
{"text_box",{text=string.format("Weapon: %s", cirnoInstance.weapon.data.name),margin=2,stroke=true,active=false,hover=false}},
|
|
{"text_box",{text=string.format("Weapon timer: %d", cirnoInstance.weapon.timer),margin=2,stroke=true,active=false,hover=false}},
|
|
{"sprite_box",{sprite=cirnoInstance.weapon.data.spriteIndex,margin=2,stroke=true,active=false,hover=false}},
|
|
}})
|
|
|
|
--pgui:component("text_box",{text=string.format("Actors: %d", count(actors)),margin=2,stroke=true,active=false,hover=false})
|
|
end
|
|
|
|
|
|
|
|
actors = {}
|
|
bullets = {}
|
|
particles = {}
|
|
|
|
function _draw()
|
|
cls(0)
|
|
|
|
camera(cirnoInstance.x - 240, cirnoInstance.y - 135)
|
|
|
|
foreach(LAYERS, render_layer)
|
|
|
|
local mx,my = mouse()
|
|
mouse_debug.draw(mx,my,4, tile_width, tile_height)
|
|
|
|
|
|
|
|
camera()
|
|
|
|
-- Draw UI
|
|
draw_ui()
|
|
weapons_manager.debug_draw()
|
|
|
|
--circfill(240,140,slidervalue,8)
|
|
|
|
end
|
|
|
|
function draw_ui()
|
|
pgui:draw()
|
|
|
|
--print(string.format("Actors: %d", count(actors)),0,32+8)
|
|
--print(string.format("%.4f %dfps",stat(1),stat(7)),2,16,5)
|
|
|
|
|
|
end
|
|
|
|
include(make_path("error_explorer") .. ".lua")
|
|
|
|
function spawn_objects()
|
|
|
|
-- Map width and height, TODO: unhardcode
|
|
local width = 32
|
|
local height = 32
|
|
|
|
for x=0,width,1 do
|
|
|
|
for y=0,height,1 do
|
|
local tile = map_manager.get_layer_tile(x,y,1)
|
|
|
|
local a = get_actor_from_sprite(tile)
|
|
if (a) then
|
|
local ai = a:new(x*tile_width,y*tile_height)
|
|
--local ai = Barrel:new(x*tile_width,y*tile_height)
|
|
--error("ads")
|
|
add(actors,ai)
|
|
end
|
|
|
|
-- if (tile == 3) then
|
|
-- local b = Barrel:new(x*tile_width,y*tile_height)
|
|
-- add(actors,b)
|
|
-- elseif(tile == 72) then
|
|
-- local s = Strawberry:new(x*tile_width,y*tile_height)
|
|
-- add(actors,s)
|
|
-- end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
function get_actor_from_sprite(sprite)
|
|
local res = nil
|
|
for a in all(actors_db) do
|
|
if (a.sprite == sprite) then
|
|
res = a.actor
|
|
end
|
|
end
|
|
return res
|
|
end
|
|
|
|
function render_layer(layer)
|
|
if (layer.render) then
|
|
-- todo move function in map manager
|
|
map(fetch("map/".. map_manager.get_current_map() .. ".map")[layer.index].bmp)
|
|
end
|
|
|
|
if (layer.render_objects) then
|
|
-- Render all objects here
|
|
--cirno.draw()
|
|
|
|
weapons_manager.draw()
|
|
|
|
for b in all(actors) do
|
|
b:draw()
|
|
end
|
|
|
|
for b in all(bullets) do
|
|
b:draw()
|
|
end
|
|
|
|
for p in all(particles) do
|
|
p:draw()
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
function distance(x1, y1, x2, y2)
|
|
return math.sqrt((x2 - x1)^2 + (y2 - y1)^2)
|
|
end
|
|
|
|
function collided(act, bul)
|
|
-- Calculate distance between actor and bullet
|
|
local dist = distance(act.x, act.y, bul.x, bul.y)
|
|
|
|
-- Check if distance is less than actor's half size and bullet's radius
|
|
return dist < (bul.radius + math.min(act.w, act.h) / 2)
|
|
end
|
|
|
|
function check_collisions()
|
|
for _, actor in ipairs(actors) do
|
|
if (actor.shootable) then
|
|
for _, bullet in ipairs(bullets) do
|
|
if collided(actor, bullet) --[[and not bullet.destroyed]] then
|
|
-- Destroy bullet
|
|
bullet:destroy()
|
|
|
|
-- Damage actor
|
|
actor:damage(bullet.damage)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
function raycast(x1, y1, x2, y2, max_distance)
|
|
local dx = x2 - x1
|
|
local dy = y2 - y1
|
|
local step_x = dx > 0 and 1 or -1
|
|
local step_y = dy > 0 and 1 or -1
|
|
dx = dx < 0 and -dx or dx
|
|
dy = dy < 0 and -dy or dy
|
|
local fraction = dx - dy
|
|
local x = x1
|
|
local y = y1
|
|
|
|
|
|
|
|
-- calculate the distance between start and end point
|
|
local distance = (math.sqrt((x2-x1)^2 + (y2-y1)^2))\1
|
|
|
|
local scale = max_distance / distance
|
|
local px = x1 + (x2 - x1) * scale
|
|
local py = y1 + (y2 - y1) * scale
|
|
|
|
-- limit the maximum distance
|
|
if distance > max_distance then
|
|
--return x2, y2, false
|
|
return px, py, false
|
|
end
|
|
|
|
-- checking the start point
|
|
--if map_manager.is_tile_shoot_solid(flr(x / tile_width), flr(y / tile_height)) then
|
|
if map_manager.is_tile_shoot_solid(x, y) then
|
|
return x1, y1, false
|
|
end
|
|
|
|
local distance_traveled = 0
|
|
|
|
while distance_traveled <= max_distance and (x ~= x2 or y ~= y2) do
|
|
local prevX = x -- store previous positions for distance calculation
|
|
local prevY = y
|
|
|
|
if fraction >= 0 then
|
|
x += step_x
|
|
fraction -= dy
|
|
else
|
|
y += step_y
|
|
fraction += dx
|
|
end
|
|
|
|
-- calculate distance traveled
|
|
distance_traveled += math.sqrt((x - prevX) ^ 2 + (y - prevY) ^ 2)\1
|
|
|
|
-- return false as soon as a solid tile is hit
|
|
if map_manager.is_tile_shoot_solid(x, y) then
|
|
if x==x2 and y==y2 then -- return true only if hit tile is destination tile
|
|
return x, y, true
|
|
else
|
|
return x, y, false
|
|
end
|
|
end
|
|
end
|
|
|
|
-- if the loop is done without hitting a solid tile, return false
|
|
return x2, y2, true
|
|
end
|
|
|