Merge branch 'world-fake3D' of game-projects/gamecore into master
This commit is contained in:
commit
696360ac30
20 changed files with 1611 additions and 32 deletions
|
@ -27,6 +27,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
|
||||
- **camera:** Add two new camera types: "middle" and "zoom".
|
||||
|
||||
- **world:** Add a fake 3D world, à la Zelda or BeatThemAll, complete with shadow support
|
||||
|
||||
### Changed
|
||||
|
||||
- **world2D:** Use a list for bodies (hitboxes, etc) and one other for actors
|
||||
|
|
13
examples/gameplay/moveplayer3D/actors/init.lua
Normal file
13
examples/gameplay/moveplayer3D/actors/init.lua
Normal file
|
@ -0,0 +1,13 @@
|
|||
local Obj = {}
|
||||
|
||||
-- On charge toutes les différentes types d'acteurs
|
||||
local cwd = (...):gsub('%.init$', '') .. "."
|
||||
Obj.Player = require(cwd .. "player")
|
||||
|
||||
Obj.index = {}
|
||||
Obj.index["player"] = Obj.Player
|
||||
|
||||
Obj.collisions = {}
|
||||
Obj.collisions["wall"] = require(cwd .. "wall")
|
||||
|
||||
return Obj
|
14
examples/gameplay/moveplayer3D/actors/parent.lua
Normal file
14
examples/gameplay/moveplayer3D/actors/parent.lua
Normal file
|
@ -0,0 +1,14 @@
|
|||
local Base = require "gamecore.modules.world.actors.actor3D"
|
||||
local Parent = Base:extend()
|
||||
|
||||
function Parent:new(world, type, x, y, z, w, h, d, isSolid)
|
||||
self.scene = world.scene
|
||||
Parent.super.new(self, world, type, x, y, z, w, h, d, isSolid)
|
||||
end
|
||||
|
||||
function Parent:draw()
|
||||
Parent.super.draw(self)
|
||||
self:drawMainHitbox()
|
||||
end
|
||||
|
||||
return Parent
|
74
examples/gameplay/moveplayer3D/actors/player.lua
Normal file
74
examples/gameplay/moveplayer3D/actors/player.lua
Normal file
|
@ -0,0 +1,74 @@
|
|||
local cwd = (...):gsub('%.player$', '') .. "."
|
||||
local Parent = require(cwd .. "parent")
|
||||
local Player = Parent:extend()
|
||||
|
||||
function Player:new(world, x, y, z, id)
|
||||
Player.super.new(self, world, "player", x, y, 0, 16, 16, 24, true)
|
||||
self:setGravity(480)
|
||||
|
||||
self:setSprite("player", 8, 12)
|
||||
self:cloneSprite()
|
||||
end
|
||||
|
||||
function Player:updateStart(dt)
|
||||
self.xfrc, self.yfrc = 480*3, 480*3
|
||||
|
||||
if self.keys["up"].isDown then
|
||||
self.ysp = -120
|
||||
end
|
||||
if self.keys["down"].isDown then
|
||||
self.ysp = 120
|
||||
end
|
||||
if self.keys["left"].isDown then
|
||||
self.xsp = -120
|
||||
end
|
||||
if self.keys["right"].isDown then
|
||||
self.xsp = 120
|
||||
end
|
||||
|
||||
if self.keys["A"].isDown and (self.onGround) then
|
||||
self.zsp = 280
|
||||
end
|
||||
end
|
||||
|
||||
function Player:updateEnd(dt)
|
||||
self:setAnimation()
|
||||
end
|
||||
|
||||
function Player:setAnimation()
|
||||
local gsp = utils.math.pointDistance(0, 0, self.xsp, self.ysp)
|
||||
self:setCustomSpeed(math.abs(gsp) / 12)
|
||||
self:setDirection(self.xsp)
|
||||
if (self.isPunching) then
|
||||
self:changeAnimation("punch", false)
|
||||
else
|
||||
if (self.onGround) then
|
||||
if (math.abs(self.xsp) > 0) or (math.abs(self.ysp) > 0) then
|
||||
self:changeAnimation("walk", false)
|
||||
else
|
||||
self:changeAnimation("idle", true)
|
||||
end
|
||||
else
|
||||
self:changeAnimation("jump", true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Player:setDirection(direction)
|
||||
direction = direction or 0
|
||||
if direction ~= 0 then
|
||||
direction = utils.math.sign(direction)
|
||||
self.direction = direction
|
||||
self:setSpriteScallingX(direction)
|
||||
end
|
||||
end
|
||||
|
||||
function Player:draw()
|
||||
Player.super.draw(self)
|
||||
end
|
||||
|
||||
function Player:drawHUD(id)
|
||||
love.graphics.print(id .. " test", 4, 4)
|
||||
end
|
||||
|
||||
return Player
|
10
examples/gameplay/moveplayer3D/actors/wall.lua
Normal file
10
examples/gameplay/moveplayer3D/actors/wall.lua
Normal file
|
@ -0,0 +1,10 @@
|
|||
local Base = require "gamecore.modules.world.actors.actor3D"
|
||||
local Wall = Base:extend()
|
||||
|
||||
function Wall:new(world, x, y, z, w, h, d)
|
||||
Wall.super.new(self, world, "wall", x, y, z, w, h, d, true)
|
||||
self:setDebugColor(0,0,0)
|
||||
self.boxes.Base(self, w, h, d)
|
||||
end
|
||||
|
||||
return Wall
|
380
examples/gameplay/moveplayer3D/assets/arena.lua
Normal file
380
examples/gameplay/moveplayer3D/assets/arena.lua
Normal file
|
@ -0,0 +1,380 @@
|
|||
return {
|
||||
version = "1.2",
|
||||
luaversion = "5.1",
|
||||
tiledversion = "1.2.2",
|
||||
orientation = "orthogonal",
|
||||
renderorder = "right-down",
|
||||
width = 30,
|
||||
height = 30,
|
||||
tilewidth = 16,
|
||||
tileheight = 16,
|
||||
nextlayerid = 5,
|
||||
nextobjectid = 18,
|
||||
properties = {},
|
||||
tilesets = {
|
||||
{
|
||||
name = "overworld",
|
||||
firstgid = 1,
|
||||
filename = "overworld.tsx",
|
||||
tilewidth = 16,
|
||||
tileheight = 16,
|
||||
spacing = 0,
|
||||
margin = 0,
|
||||
columns = 32,
|
||||
image = "overworld.png",
|
||||
imagewidth = 512,
|
||||
imageheight = 240,
|
||||
tileoffset = {
|
||||
x = 0,
|
||||
y = 0
|
||||
},
|
||||
grid = {
|
||||
orientation = "orthogonal",
|
||||
width = 16,
|
||||
height = 16
|
||||
},
|
||||
properties = {},
|
||||
terrains = {},
|
||||
tilecount = 480,
|
||||
tiles = {}
|
||||
}
|
||||
},
|
||||
layers = {
|
||||
{
|
||||
type = "tilelayer",
|
||||
id = 1,
|
||||
name = "Calque de Tile 1",
|
||||
x = 0,
|
||||
y = 0,
|
||||
width = 30,
|
||||
height = 30,
|
||||
visible = true,
|
||||
opacity = 1,
|
||||
offsetx = 0,
|
||||
offsety = 0,
|
||||
properties = {},
|
||||
encoding = "lua",
|
||||
data = {
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 399, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 400, 3,
|
||||
3, 339, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, 337, 3,
|
||||
3, 339, 434, 434, 434, 434, 434, 434, 434, 434, 434, 434, 434, 434, 434, 434, 434, 434, 434, 434, 434, 434, 434, 434, 434, 434, 434, 434, 337, 3,
|
||||
3, 339, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 337, 3,
|
||||
3, 339, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 337, 3,
|
||||
3, 339, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 337, 3,
|
||||
3, 339, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 337, 3,
|
||||
3, 339, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 337, 3,
|
||||
3, 339, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 337, 3,
|
||||
3, 339, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 337, 3,
|
||||
3, 339, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 337, 3,
|
||||
3, 339, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 337, 3,
|
||||
3, 339, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 337, 3,
|
||||
3, 339, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 337, 3,
|
||||
3, 339, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 337, 3,
|
||||
3, 339, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 337, 3,
|
||||
3, 339, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 337, 3,
|
||||
3, 339, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 337, 3,
|
||||
3, 339, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 337, 3,
|
||||
3, 339, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 337, 3,
|
||||
3, 339, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 337, 3,
|
||||
3, 339, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 337, 3,
|
||||
3, 339, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 337, 3,
|
||||
3, 339, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 337, 3,
|
||||
3, 339, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 337, 3,
|
||||
3, 339, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 337, 3,
|
||||
3, 339, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 337, 3,
|
||||
3, 431, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, 432, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
|
||||
}
|
||||
},
|
||||
{
|
||||
type = "tilelayer",
|
||||
id = 2,
|
||||
name = "Rochers",
|
||||
x = 0,
|
||||
y = 0,
|
||||
width = 30,
|
||||
height = 30,
|
||||
visible = true,
|
||||
opacity = 1,
|
||||
offsetx = 0,
|
||||
offsety = 0,
|
||||
properties = {},
|
||||
encoding = "lua",
|
||||
data = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 85, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 84, 85, 0, 0, 0, 0, 0, 0, 0, 0, 84, 85, 0, 0, 0, 0, 116, 117, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 116, 117, 0, 0, 0, 0, 0, 0, 0, 0, 116, 117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 85, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 84, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 117, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 116, 117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 84, 85, 0, 0, 0, 0, 0, 0, 116, 117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 116, 117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
}
|
||||
},
|
||||
{
|
||||
type = "objectgroup",
|
||||
id = 3,
|
||||
name = "player",
|
||||
visible = true,
|
||||
opacity = 1,
|
||||
offsetx = 0,
|
||||
offsety = 0,
|
||||
draworder = "topdown",
|
||||
properties = {},
|
||||
objects = {
|
||||
{
|
||||
id = 1,
|
||||
name = "",
|
||||
type = "",
|
||||
shape = "rectangle",
|
||||
x = 48,
|
||||
y = 80,
|
||||
width = 16,
|
||||
height = 16,
|
||||
rotation = 0,
|
||||
visible = true,
|
||||
properties = {
|
||||
["id"] = 1
|
||||
}
|
||||
},
|
||||
{
|
||||
id = 2,
|
||||
name = "",
|
||||
type = "",
|
||||
shape = "rectangle",
|
||||
x = 416,
|
||||
y = 80,
|
||||
width = 16,
|
||||
height = 16,
|
||||
rotation = 0,
|
||||
visible = true,
|
||||
properties = {
|
||||
["id"] = 1
|
||||
}
|
||||
},
|
||||
{
|
||||
id = 3,
|
||||
name = "",
|
||||
type = "",
|
||||
shape = "rectangle",
|
||||
x = 48,
|
||||
y = 416,
|
||||
width = 16,
|
||||
height = 16,
|
||||
rotation = 0,
|
||||
visible = true,
|
||||
properties = {
|
||||
["id"] = 3
|
||||
}
|
||||
},
|
||||
{
|
||||
id = 4,
|
||||
name = "",
|
||||
type = "",
|
||||
shape = "rectangle",
|
||||
x = 416,
|
||||
y = 416,
|
||||
width = 16,
|
||||
height = 16,
|
||||
rotation = 0,
|
||||
visible = true,
|
||||
properties = {
|
||||
["id"] = 4
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
type = "objectgroup",
|
||||
id = 4,
|
||||
name = "wall",
|
||||
visible = true,
|
||||
opacity = 1,
|
||||
offsetx = 0,
|
||||
offsety = 0,
|
||||
draworder = "topdown",
|
||||
properties = {},
|
||||
objects = {
|
||||
{
|
||||
id = 5,
|
||||
name = "",
|
||||
type = "",
|
||||
shape = "rectangle",
|
||||
x = 0,
|
||||
y = 0,
|
||||
width = 480,
|
||||
height = 64,
|
||||
rotation = 0,
|
||||
visible = true,
|
||||
properties = {}
|
||||
},
|
||||
{
|
||||
id = 6,
|
||||
name = "",
|
||||
type = "",
|
||||
shape = "rectangle",
|
||||
x = 448,
|
||||
y = 64,
|
||||
width = 32,
|
||||
height = 416,
|
||||
rotation = 0,
|
||||
visible = true,
|
||||
properties = {}
|
||||
},
|
||||
{
|
||||
id = 7,
|
||||
name = "",
|
||||
type = "",
|
||||
shape = "rectangle",
|
||||
x = 32,
|
||||
y = 448,
|
||||
width = 416,
|
||||
height = 32,
|
||||
rotation = 0,
|
||||
visible = true,
|
||||
properties = {}
|
||||
},
|
||||
{
|
||||
id = 8,
|
||||
name = "",
|
||||
type = "",
|
||||
shape = "rectangle",
|
||||
x = 0,
|
||||
y = 64,
|
||||
width = 32,
|
||||
height = 416,
|
||||
rotation = 0,
|
||||
visible = true,
|
||||
properties = {}
|
||||
},
|
||||
{
|
||||
id = 9,
|
||||
name = "",
|
||||
type = "",
|
||||
shape = "rectangle",
|
||||
x = 112,
|
||||
y = 128,
|
||||
width = 32,
|
||||
height = 32,
|
||||
rotation = 0,
|
||||
visible = true,
|
||||
properties = {}
|
||||
},
|
||||
{
|
||||
id = 10,
|
||||
name = "",
|
||||
type = "",
|
||||
shape = "rectangle",
|
||||
x = 272,
|
||||
y = 128,
|
||||
width = 32,
|
||||
height = 32,
|
||||
rotation = 0,
|
||||
visible = true,
|
||||
properties = {}
|
||||
},
|
||||
{
|
||||
id = 12,
|
||||
name = "",
|
||||
type = "",
|
||||
shape = "rectangle",
|
||||
x = 368,
|
||||
y = 112,
|
||||
width = 32,
|
||||
height = 32,
|
||||
rotation = 0,
|
||||
visible = true,
|
||||
properties = {}
|
||||
},
|
||||
{
|
||||
id = 13,
|
||||
name = "",
|
||||
type = "",
|
||||
shape = "rectangle",
|
||||
x = 192,
|
||||
y = 224,
|
||||
width = 32,
|
||||
height = 32,
|
||||
rotation = 0,
|
||||
visible = true,
|
||||
properties = {}
|
||||
},
|
||||
{
|
||||
id = 14,
|
||||
name = "",
|
||||
type = "",
|
||||
shape = "rectangle",
|
||||
x = 352,
|
||||
y = 272,
|
||||
width = 32,
|
||||
height = 32,
|
||||
rotation = 0,
|
||||
visible = true,
|
||||
properties = {}
|
||||
},
|
||||
{
|
||||
id = 15,
|
||||
name = "",
|
||||
type = "",
|
||||
shape = "rectangle",
|
||||
x = 256,
|
||||
y = 368,
|
||||
width = 32,
|
||||
height = 32,
|
||||
rotation = 0,
|
||||
visible = true,
|
||||
properties = {}
|
||||
},
|
||||
{
|
||||
id = 16,
|
||||
name = "",
|
||||
type = "",
|
||||
shape = "rectangle",
|
||||
x = 128,
|
||||
y = 384,
|
||||
width = 32,
|
||||
height = 32,
|
||||
rotation = 0,
|
||||
visible = true,
|
||||
properties = {}
|
||||
},
|
||||
{
|
||||
id = 17,
|
||||
name = "",
|
||||
type = "",
|
||||
shape = "rectangle",
|
||||
x = 80,
|
||||
y = 288,
|
||||
width = 32,
|
||||
height = 32,
|
||||
rotation = 0,
|
||||
visible = true,
|
||||
properties = {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
108
examples/gameplay/moveplayer3D/assets/arena.tmx
Normal file
108
examples/gameplay/moveplayer3D/assets/arena.tmx
Normal file
|
@ -0,0 +1,108 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<map version="1.2" tiledversion="1.2.2" orientation="orthogonal" renderorder="right-down" width="30" height="30" tilewidth="16" tileheight="16" infinite="0" nextlayerid="5" nextobjectid="18">
|
||||
<tileset firstgid="1" source="overworld.tsx"/>
|
||||
<layer id="1" name="Calque de Tile 1" width="30" height="30">
|
||||
<data encoding="csv">
|
||||
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
|
||||
3,399,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,400,3,
|
||||
3,339,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,337,3,
|
||||
3,339,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,337,3,
|
||||
3,339,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,337,3,
|
||||
3,339,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,337,3,
|
||||
3,339,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,337,3,
|
||||
3,339,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,337,3,
|
||||
3,339,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,337,3,
|
||||
3,339,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,337,3,
|
||||
3,339,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,337,3,
|
||||
3,339,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,337,3,
|
||||
3,339,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,337,3,
|
||||
3,339,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,337,3,
|
||||
3,339,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,337,3,
|
||||
3,339,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,337,3,
|
||||
3,339,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,337,3,
|
||||
3,339,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,337,3,
|
||||
3,339,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,337,3,
|
||||
3,339,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,337,3,
|
||||
3,339,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,337,3,
|
||||
3,339,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,337,3,
|
||||
3,339,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,337,3,
|
||||
3,339,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,337,3,
|
||||
3,339,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,337,3,
|
||||
3,339,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,337,3,
|
||||
3,339,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,337,3,
|
||||
3,339,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,337,3,
|
||||
3,431,306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,432,3,
|
||||
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3
|
||||
</data>
|
||||
</layer>
|
||||
<layer id="2" name="Rochers" width="30" height="30">
|
||||
<data encoding="csv">
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,85,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,84,85,0,0,0,0,0,0,0,0,84,85,0,0,0,0,116,117,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,116,117,0,0,0,0,0,0,0,0,116,117,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,84,85,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,116,117,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,85,0,0,0,0,0,0,
|
||||
0,0,0,0,0,84,85,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,116,117,0,0,0,0,0,0,
|
||||
0,0,0,0,0,116,117,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,85,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,84,85,0,0,0,0,0,0,116,117,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,116,117,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
</data>
|
||||
</layer>
|
||||
<objectgroup id="3" name="player">
|
||||
<object id="1" x="48" y="80" width="16" height="16">
|
||||
<properties>
|
||||
<property name="id" type="int" value="1"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="2" x="416" y="80" width="16" height="16">
|
||||
<properties>
|
||||
<property name="id" type="int" value="1"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="3" x="48" y="416" width="16" height="16">
|
||||
<properties>
|
||||
<property name="id" type="int" value="3"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="4" x="416" y="416" width="16" height="16">
|
||||
<properties>
|
||||
<property name="id" type="int" value="4"/>
|
||||
</properties>
|
||||
</object>
|
||||
</objectgroup>
|
||||
<objectgroup id="4" name="wall">
|
||||
<object id="5" x="0" y="0" width="480" height="64"/>
|
||||
<object id="6" x="448" y="64" width="32" height="416"/>
|
||||
<object id="7" x="32" y="448" width="416" height="32"/>
|
||||
<object id="8" x="0" y="64" width="32" height="416"/>
|
||||
<object id="9" x="112" y="128" width="32" height="32"/>
|
||||
<object id="10" x="272" y="128" width="32" height="32"/>
|
||||
<object id="12" x="368" y="112" width="32" height="32"/>
|
||||
<object id="13" x="192" y="224" width="32" height="32"/>
|
||||
<object id="14" x="352" y="272" width="32" height="32"/>
|
||||
<object id="15" x="256" y="368" width="32" height="32"/>
|
||||
<object id="16" x="128" y="384" width="32" height="32"/>
|
||||
<object id="17" x="80" y="288" width="32" height="32"/>
|
||||
</objectgroup>
|
||||
</map>
|
BIN
examples/gameplay/moveplayer3D/assets/overworld.png
Normal file
BIN
examples/gameplay/moveplayer3D/assets/overworld.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
4
examples/gameplay/moveplayer3D/assets/overworld.tsx
Normal file
4
examples/gameplay/moveplayer3D/assets/overworld.tsx
Normal file
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<tileset version="1.2" tiledversion="1.2.2" name="overworld" tilewidth="16" tileheight="16" tilecount="480" columns="32">
|
||||
<image source="overworld.png" width="512" height="240"/>
|
||||
</tileset>
|
40
examples/gameplay/moveplayer3D/init.lua
Normal file
40
examples/gameplay/moveplayer3D/init.lua
Normal file
|
@ -0,0 +1,40 @@
|
|||
-- scenes/moveplayer3D :: a basic player movement example in fake3D
|
||||
|
||||
--[[
|
||||
Copyright © 2019 Kazhnuz
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
]]
|
||||
|
||||
local Scene = require "gamecore.modules.scenes"
|
||||
local MovePlayer = Scene:extend()
|
||||
|
||||
local World = require "gamecore.modules.world.world3D"
|
||||
|
||||
function MovePlayer:new()
|
||||
MovePlayer.super.new(self)
|
||||
self.assets:batchImport("examples.gameplay.plateform.assets")
|
||||
|
||||
World(self, "examples.gameplay.moveplayer3D.actors", "examples/gameplay/moveplayer3D/assets/arena.lua")
|
||||
self.world:setPlayerNumber(1)
|
||||
|
||||
self.world:loadMap()
|
||||
self.world.obj.collisions["wall"](self.world, 0,0,-16,1000, 1000, 16)
|
||||
end
|
||||
|
||||
return MovePlayer
|
|
@ -6,5 +6,6 @@ return {
|
|||
Inventory = require "examples.menus.inventory",
|
||||
Options = require "examples.menus.options",
|
||||
MovePlayer = require "examples.gameplay.moveplayer",
|
||||
MovePlayer3D = require "examples.gameplay.moveplayer3D",
|
||||
Plateformer = require "examples.gameplay.plateform"
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ function MainMenu:new()
|
|||
self:addSubMenu("gameplay", "gameplay")
|
||||
self:addScene("gameplay", examples.MovePlayer, "movable")
|
||||
self:addScene("gameplay", examples.Plateformer, "plateform")
|
||||
|
||||
self:addScene("gameplay", examples.MovePlayer3D, "movable3D")
|
||||
|
||||
self.menusystem:setSoundFromSceneAssets("navigate")
|
||||
|
||||
|
|
|
@ -193,6 +193,10 @@ end
|
|||
-- DRAW FUNCTIONS
|
||||
-- Draw the actors.
|
||||
|
||||
function Actor3D:getShape()
|
||||
return (self.x), (self.y), self.w, (self.h)
|
||||
end
|
||||
|
||||
function Actor2D:draw()
|
||||
self:drawStart()
|
||||
local x, y = math.floor(self.x), math.floor(self.y)
|
||||
|
|
297
gamecore/modules/world/actors/actor3D.lua
Normal file
297
gamecore/modules/world/actors/actor3D.lua
Normal file
|
@ -0,0 +1,297 @@
|
|||
-- actor3D.lua :: the implementation of a 2D actor. It contain every element
|
||||
-- needed to create your own 2D actors.
|
||||
|
||||
--[[
|
||||
Copyright © 2019 Kazhnuz
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
]]
|
||||
|
||||
local cwd = (...):gsub('%.actor3D$', '') .. "."
|
||||
local BaseActor = require(cwd .. "baseactor")
|
||||
local Actor3D = BaseActor:extend()
|
||||
|
||||
local Hitbox = require(cwd .. "utils.hitbox3D")
|
||||
local Boxes = require(cwd .. "utils.boxes")
|
||||
|
||||
-- INIT FUNCTIONS
|
||||
-- Initialise the actor and its base functions
|
||||
|
||||
function Actor3D:new(world, type, x, y, z, w, h, d, isSolid)
|
||||
Actor3D.super.new(self, world, type, x, y, z, w, h, d, isSolid)
|
||||
self:initHitboxes()
|
||||
self.world:registerShape(self)
|
||||
self.boxes = Boxes
|
||||
self.doCastShadows = true
|
||||
end
|
||||
|
||||
function Actor3D:destroy()
|
||||
self:removeOldShadowTargets()
|
||||
if self.box ~= nil then
|
||||
self.world:removeTerrain(self)
|
||||
end
|
||||
self.world:removeActor(self)
|
||||
self.mainHitbox:destroy()
|
||||
self.world:removeShape(self)
|
||||
self.isDestroyed = true
|
||||
end
|
||||
|
||||
-- PHYSICS FUNCTIONS
|
||||
-- Handle movement and collisions.
|
||||
|
||||
function Actor3D:autoMove(dt)
|
||||
self:updateHitboxes()
|
||||
self.onGround = false
|
||||
self:applyGravity(dt)
|
||||
|
||||
local dx, dy, dz = self:getFuturePosition(dt)
|
||||
local newx, newy, newz, cols, colNumber = self:move(dx, dy, dz)
|
||||
|
||||
-- apply after the movement the friction, until the player stop
|
||||
-- note: the friction is applied according to the delta time,
|
||||
-- thus the friction should be how much speed is substracted in 1 second
|
||||
|
||||
self:solveAllCollisions(cols)
|
||||
|
||||
self:applyFriction(dt)
|
||||
end
|
||||
|
||||
function Actor3D:changeSpeedToCollisionNormal(normal)
|
||||
local xsp, ysp, zsp = self.xsp, self.ysp, self.zsp
|
||||
local nx, ny, nz = normal.x, normal.y, normal.z
|
||||
|
||||
if (nx < 0 and xsp > 0) or (nx > 0 and xsp < 0) then
|
||||
xsp = -xsp * self.bounceFactor
|
||||
end
|
||||
|
||||
if (ny < 0 and ysp > 0) or (ny > 0 and ysp < 0) then
|
||||
ysp = -ysp * self.bounceFactor
|
||||
end
|
||||
|
||||
if (nz < 0 and zsp > 0) or (nz > 0 and zsp < 0) then
|
||||
zsp = -zsp * self.bounceFactor
|
||||
end
|
||||
|
||||
self.xsp, self.ysp, self.zsp = xsp, ysp, zsp
|
||||
end
|
||||
|
||||
function Actor3D:move(dx, dy, dz)
|
||||
local cols, colNumber = {}, 0
|
||||
local oldx, oldy, oldz = self.x, self.y, self.z
|
||||
if (self.isDestroyed == false) then
|
||||
self.x, self.y, self.z, cols, colNumber = self.mainHitbox:checkCollision(dx, dy, dz, self.filter)
|
||||
self.mainHitbox:updatePosition()
|
||||
self.world:updateShape(self)
|
||||
end
|
||||
|
||||
if (oldx ~= self.x) or (oldy ~= self.y) or (oldz ~= self.z) or (self.shadowTargetsPrevious == nil) then
|
||||
if (self.doCastShadows) then
|
||||
self:castShadow()
|
||||
end
|
||||
end
|
||||
|
||||
return self.x, self.y, self.z, cols, colNumber
|
||||
end
|
||||
|
||||
function Actor3D:checkCollision(dx, dy, dz)
|
||||
local x, y, z, cols, colNumber = dx, dy, dz, {}, 0
|
||||
if (self.isDestroyed == false) then
|
||||
x, y, z, cols, colNumber = self.mainHitbox:checkCollision(dx, dy, dz, self.filter)
|
||||
end
|
||||
return self.x, self.y, self.z, cols, colNumber
|
||||
end
|
||||
|
||||
-- GRAVITY SYSTEM FUNCTIONS
|
||||
-- All functions related to gravity
|
||||
|
||||
function Actor3D:applyGravity(dt)
|
||||
local grav = self.grav * -1
|
||||
self.zsp = self.zsp + (grav * dt)
|
||||
|
||||
if utils.math.sign(self.zsp) == utils.math.sign(grav) then
|
||||
self:checkGround( )
|
||||
end
|
||||
end
|
||||
|
||||
function Actor3D:checkGround()
|
||||
local dx, dy, dz = self.x, self.y, self.z - utils.math.sign(self.grav)
|
||||
local newx, newy, newz, cols, colNumber = self:checkCollision(dx, dy, dz)
|
||||
for i, col in ipairs(cols) do
|
||||
if (col.type == "touch") or (col.type == "bounce") or (col.type == "slide") then
|
||||
if not (self.grav == 0) then
|
||||
if col.normal.z == utils.math.sign(self.grav) then self.onGround = true end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- COORDINATE/MOVEMENT FUNCTIONS
|
||||
-- Handle coordinate
|
||||
|
||||
function Actor3D:getViewCenter()
|
||||
local x, y, z = self:getCenter()
|
||||
return x, y - (self.d/2)
|
||||
end
|
||||
|
||||
-- HITBOXES FUNCTIONS
|
||||
-- Functions related to actor hitboxes
|
||||
|
||||
function Actor3D:addHitboxFromFrameData(framedata, animationID, frameID, hitboxID)
|
||||
local sx, sy = self:getSpriteScalling()
|
||||
local type = framedata[1]
|
||||
local ox = framedata[2]
|
||||
local oy = framedata[3]
|
||||
local oz = framedata[4]
|
||||
local w = framedata[5]
|
||||
local h = framedata[6]
|
||||
local d = framedata[7]
|
||||
local isSolid = framedata[8] or false
|
||||
local anim = animationID or "null"
|
||||
local frame = frameID or 0
|
||||
local id = hitboxID or 0
|
||||
if (sx < 0) then
|
||||
ox = self.w - ox - w
|
||||
end
|
||||
if (sy < 0) then
|
||||
oz = self.d - oz - d
|
||||
end
|
||||
|
||||
if (type == "main") then
|
||||
self.mainHitbox:modify(ox, oy, oz, w, h, d)
|
||||
else
|
||||
local hitboxName = anim .. frame .. type .. id
|
||||
self:addHitbox(hitboxName, type, ox, oy, oz, w, h, d, isSolid)
|
||||
return hitboxName
|
||||
end
|
||||
end
|
||||
|
||||
function Actor3D:initMainHitbox()
|
||||
self.mainHitbox = Hitbox(self, self.type, 0, 0, 0, self.w, self.h, self.d, self.isSolid)
|
||||
self.mainHitbox:advertiseAsMainHitbox()
|
||||
end
|
||||
|
||||
function Actor3D:addHitbox(name, type, ox, oy, oz, w, h, d, isSolid)
|
||||
if (self.hitboxes[name] ~= nil) then
|
||||
print("ERROR:", "The hitbox " .. name .. " already exists")
|
||||
else
|
||||
local hitbox = Hitbox(self, type, ox, oy, oz, w, h, d, isSolid)
|
||||
self.hitboxes[name] = hitbox
|
||||
return hitbox
|
||||
end
|
||||
end
|
||||
|
||||
function Actor3D:checkHitboxCollisions(name, filter)
|
||||
self:checkHitboxCollisionsAtPoint(name, self.x, self.y, self.z, filter)
|
||||
end
|
||||
|
||||
function Actor3D:checkHitboxCollisionsAtPoint(name, dx, dy, dz, filter)
|
||||
local x, y, z, cols, colNumber = dx, dy, dz, {}, 0
|
||||
local filter = filter or self.filter
|
||||
if (self.isDestroyed == false) and (self.hitboxes[name] ~= nil) then
|
||||
x, y, z, cols, colNumber = self.hitboxes[name]:checkCollision(dx, dy, dz, filter)
|
||||
local type = self.hitboxes[name].type
|
||||
|
||||
for i, col in ipairs(cols) do
|
||||
self:hitboxResponse(name, type, col)
|
||||
end
|
||||
end
|
||||
|
||||
return x, y, z, cols, colNumber
|
||||
end
|
||||
|
||||
-- SHADOW FUNCTIONS
|
||||
-- Handle everything related to shadow
|
||||
|
||||
function Actor3D:castShadow()
|
||||
local shadowTargets = self.world:getTerrainInRect(self.x, self.y, self.w, self.d)
|
||||
-- initialize the shadowTargetsPrevious variable if it doesn't exist
|
||||
if (self.shadowTargetsPrevious == nil) then
|
||||
self.shadowTargetsPrevious = {}
|
||||
end
|
||||
|
||||
for i, target in ipairs(shadowTargets) do
|
||||
-- We test if the actor is below the current actor
|
||||
if (target ~= self) and (target.box ~= nil) then
|
||||
|
||||
if (target.z + target.d <= self.z + self.d) then
|
||||
-- Remove the target of the list of item targeted last update,
|
||||
-- in order to only have object no longer shadowed after the
|
||||
-- end of the loop
|
||||
for j, oldtarget in ipairs(self.shadowTargetsPrevious) do
|
||||
if (target == oldtarget) then
|
||||
table.remove(self.shadowTargetsPrevious, j)
|
||||
end
|
||||
end
|
||||
|
||||
-- We update the shadow source
|
||||
local x, y = math.floor(self.x - target.x), math.floor(self.y - target.y)
|
||||
target.box:setShadowSource(self, x, y)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- At this point, if a target is still in the shadowTargetsPrevious list,
|
||||
-- it mean that it's not shadowed. So we can simply remove the shadow.
|
||||
self:removeOldShadowTargets()
|
||||
|
||||
self.shadowTargetsPrevious = shadowTargets
|
||||
end
|
||||
|
||||
function Actor3D:removeOldShadowTargets()
|
||||
if (self.shadowTargetsPrevious ~= nil) then
|
||||
for i, target in ipairs(self.shadowTargetsPrevious) do
|
||||
if (target.box ~= nil) then
|
||||
target.box:removeShadowSource(self)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Actor3D:redrawShadowCanvas()
|
||||
if (self.box ~= nil) then
|
||||
self.box:redrawShadowCanvas()
|
||||
end
|
||||
end
|
||||
|
||||
-- DRAW FUNCTIONS
|
||||
-- Draw the actors.
|
||||
|
||||
function Actor3D:drawShadow(x, y)
|
||||
love.graphics.setColor(0, 0, 0, 1)
|
||||
love.graphics.rectangle("fill", x, y, self.w, self.h)
|
||||
utils.graphics.resetColor()
|
||||
end
|
||||
|
||||
function Actor3D:getShape()
|
||||
return (self.x), (self.y - self.z - self.d), self.w, (self.h + self.d)
|
||||
end
|
||||
|
||||
function Actor3D:draw()
|
||||
self:drawStart()
|
||||
if (self.box ~= nil) then
|
||||
self.box:draw(self.x, self.y, self.z)
|
||||
else
|
||||
local x, y = math.floor(self.x), math.floor(self.y - self.z - self.d + (self.h/2))
|
||||
self:drawSprite(x, y)
|
||||
end
|
||||
self:drawEnd()
|
||||
end
|
||||
|
||||
return Actor3D
|
30
gamecore/modules/world/actors/utils/boxes/init.lua
Normal file
30
gamecore/modules/world/actors/utils/boxes/init.lua
Normal file
|
@ -0,0 +1,30 @@
|
|||
-- box3D :: drawable box with shadow handling for fake3D actors
|
||||
|
||||
--[[
|
||||
Copyright © 2019 Kazhnuz
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
]]
|
||||
|
||||
local cwd = (...):gsub('%.init$', '') .. "."
|
||||
|
||||
local Boxes = {}
|
||||
|
||||
Boxes.Base = require(cwd .. "parent")
|
||||
|
||||
return Boxes
|
156
gamecore/modules/world/actors/utils/boxes/parent.lua
Normal file
156
gamecore/modules/world/actors/utils/boxes/parent.lua
Normal file
|
@ -0,0 +1,156 @@
|
|||
-- box3D :: drawable box with shadow handling for fake3D actors
|
||||
|
||||
--[[
|
||||
Copyright © 2019 Kazhnuz
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
]]
|
||||
|
||||
local Box3D = Object:extend()
|
||||
|
||||
function Box3D:new(owner, w, h, d)
|
||||
self.owner = owner
|
||||
self.world = owner.world
|
||||
self.cameras = self.world.cameras
|
||||
|
||||
self.w = w
|
||||
self.h = h
|
||||
self.d = d
|
||||
|
||||
self.haveLine = true
|
||||
|
||||
self.shadowSources = {}
|
||||
self.needRedraw = false
|
||||
|
||||
self.texture = {}
|
||||
self:setTopTexture()
|
||||
self:setBottomTexture()
|
||||
self.texture.shadows = nil
|
||||
|
||||
self:register()
|
||||
end
|
||||
|
||||
function Box3D:register()
|
||||
self.owner.box = self
|
||||
self.world:registerTerrain(self.owner)
|
||||
end
|
||||
|
||||
function Box3D:setSizeFromOwner()
|
||||
self:setSize(self.owner.w, self.owner.h, self.owner.d)
|
||||
end
|
||||
|
||||
function Box3D:setSize()
|
||||
self.w = w
|
||||
self.h = h
|
||||
self.d = d
|
||||
|
||||
self:regenerate()
|
||||
end
|
||||
|
||||
function Box3D:setTopTexture()
|
||||
local canvas = love.graphics.newCanvas(self.w, self.h)
|
||||
love.graphics.setCanvas( canvas )
|
||||
utils.graphics.resetColor()
|
||||
love.graphics.rectangle("fill", 0, 0, self.w, self.h)
|
||||
love.graphics.setCanvas( )
|
||||
local imagedata = canvas:newImageData()
|
||||
self.texture.top = love.graphics.newImage( imagedata )
|
||||
imagedata:release()
|
||||
canvas:release()
|
||||
end
|
||||
|
||||
function Box3D:setBottomTexture()
|
||||
local canvas = love.graphics.newCanvas(self.w, self.d)
|
||||
love.graphics.setCanvas( canvas )
|
||||
love.graphics.setColor(0.9, 0.9, 0.9, 1)
|
||||
love.graphics.rectangle("fill", 0, 0, self.w, self.d)
|
||||
utils.graphics.resetColor()
|
||||
love.graphics.setCanvas( )
|
||||
local imagedata = canvas:newImageData()
|
||||
self.texture.bottom = love.graphics.newImage( imagedata )
|
||||
imagedata:release()
|
||||
canvas:release()
|
||||
end
|
||||
|
||||
function Box3D:setShadowSource(actor, x, y)
|
||||
local foundShadow = false
|
||||
|
||||
for i,v in ipairs(self.shadowSources) do
|
||||
if (v.actor == actor) then
|
||||
if (v.x ~= x) or (v.y ~= y) then
|
||||
v.x = x
|
||||
v.y = y
|
||||
self.needRedraw = true
|
||||
end
|
||||
foundShadow = true
|
||||
end
|
||||
end
|
||||
|
||||
if (foundShadow == false) then
|
||||
local shadow = {}
|
||||
shadow.actor = actor
|
||||
shadow.x = x
|
||||
shadow.y = y
|
||||
self.needRedraw = true
|
||||
|
||||
table.insert(self.shadowSources, shadow)
|
||||
end
|
||||
end
|
||||
|
||||
function Box3D:removeShadowSource(actor)
|
||||
for i,v in ipairs(self.shadowSources) do
|
||||
if (v.actor == actor) then
|
||||
table.remove(self.shadowSources, i)
|
||||
self.needRedraw = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Box3D:redrawShadowCanvas()
|
||||
if (self.needRedraw) then
|
||||
local canvas = love.graphics.newCanvas(self.w, self.h)
|
||||
love.graphics.setCanvas( canvas )
|
||||
for i,v in ipairs(self.shadowSources) do
|
||||
v.actor:drawShadow(v.x, v.y)
|
||||
end
|
||||
|
||||
love.graphics.setCanvas( )
|
||||
|
||||
local imagedata = canvas:newImageData()
|
||||
self.texture.shadows = love.graphics.newImage( imagedata )
|
||||
imagedata:release()
|
||||
canvas:release()
|
||||
|
||||
self.needRedraw = false
|
||||
end
|
||||
end
|
||||
|
||||
function Box3D:draw(x, y, z)
|
||||
love.graphics.setColor(0, 0, 0, 1)
|
||||
if (self.haveLine) then
|
||||
love.graphics.rectangle("line", x, (y-z) - (self.d), self.w, self.d + self.h)
|
||||
end
|
||||
utils.graphics.resetColor()
|
||||
love.graphics.draw(self.texture.top, x, (y-z) - (self.d))
|
||||
love.graphics.draw(self.texture.bottom, x, (y-z) - (self.d) + (self.h))
|
||||
if (self.texture.shadows ~= nil) and (#self.shadowSources > 0) then
|
||||
love.graphics.draw(self.texture.shadows, x, (y-z) - (self.d))
|
||||
end
|
||||
end
|
||||
|
||||
return Box3D
|
129
gamecore/modules/world/actors/utils/hitbox3D.lua
Normal file
129
gamecore/modules/world/actors/utils/hitbox3D.lua
Normal file
|
@ -0,0 +1,129 @@
|
|||
-- hitbox3D.lua :: a basic 3D hitbox object. It's used by the actors to check
|
||||
-- collisions and to handle different type of responses.
|
||||
|
||||
--[[
|
||||
Copyright © 2019 Kazhnuz
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
]]
|
||||
|
||||
local Hitbox3D = Object:extend()
|
||||
|
||||
-- INIT FUNCTIONS
|
||||
-- Initialise the actor and its base functions
|
||||
|
||||
function Hitbox3D:new(owner, type, ox, oy, oz, w, h, d, isSolid)
|
||||
self.owner = owner
|
||||
self.world = owner.world
|
||||
|
||||
self.type = type
|
||||
self.ox = ox
|
||||
self.oy = oy
|
||||
self.oz = oz
|
||||
self.x, self.y, self.z = self:getPosition()
|
||||
self.w = w
|
||||
self.h = h
|
||||
self.d = d
|
||||
self.isSolid = isSolid
|
||||
|
||||
self.isMainHitBox = false
|
||||
|
||||
self:setDebugColor(0,0,0)
|
||||
self:register()
|
||||
end
|
||||
|
||||
function Hitbox3D:advertiseAsMainHitbox()
|
||||
self.isMainHitBox = true
|
||||
end
|
||||
|
||||
function Hitbox3D:modify(ox, oy, oz, w, h, d)
|
||||
self.ox = ox
|
||||
self.oy = oy
|
||||
self.oz = oz
|
||||
self.x, self.y, self.z = self:getPosition()
|
||||
self.w = w
|
||||
self.h = h
|
||||
self.d = d
|
||||
end
|
||||
|
||||
function Hitbox3D:setDebugColor(r,g,b)
|
||||
self.debug = {}
|
||||
self.debug.r = r
|
||||
self.debug.g = g
|
||||
self.debug.b = b
|
||||
end
|
||||
|
||||
function Hitbox3D:register()
|
||||
self.world:registerBody(self)
|
||||
end
|
||||
|
||||
function Hitbox3D:destroy()
|
||||
self.world:removeBody(self)
|
||||
end
|
||||
|
||||
-- COORDINATE FUNCTIONS
|
||||
-- Handle Hitbox position
|
||||
|
||||
function Hitbox3D:updatePosition()
|
||||
self.x, self.y, self.z = self:getPosition()
|
||||
self.world:updateBody(self)
|
||||
return self.x, self.y, self.z
|
||||
end
|
||||
|
||||
function Hitbox3D:getPosition()
|
||||
return self.ox + self.owner.x, self.oy + self.owner.y, self.oz + self.owner.z
|
||||
end
|
||||
|
||||
function Hitbox3D:getOwnerPosition()
|
||||
return self.x - self.ox, self.y - self.oy, self.z - self.oz
|
||||
end
|
||||
|
||||
function Hitbox3D:getNewOwnerPosition(x, y, z)
|
||||
return x - self.ox, y - self.oy, z - self.oz
|
||||
end
|
||||
|
||||
function Hitbox3D:getCenter()
|
||||
return self.x + (self.w/2), self.y + (self.h/2), self.z + (self.d/2)
|
||||
end
|
||||
|
||||
-- COLLISION FUNCTIONS
|
||||
-- Handle Hitbox position
|
||||
|
||||
function Hitbox3D:checkCollision(dx, dy, dz, filter)
|
||||
self:updatePosition()
|
||||
|
||||
local dx, dy = self.ox + dx, self.oy + dy, self.oz + dz
|
||||
local x, y, z, cols, colNumber = self.world:checkCollision(self, dx, dy, dz, filter)
|
||||
local newx, newy, newz = self:getNewOwnerPosition(x, y, z)
|
||||
|
||||
return newx, newy, newz, cols, colNumber
|
||||
end
|
||||
|
||||
-- DRAW FUNCTIONS
|
||||
-- Just some debug function to draw hitbox
|
||||
|
||||
function Hitbox3D:draw()
|
||||
local x, y, z = self:getPosition()
|
||||
love.graphics.setColor(self.debug.r, self.debug.g, self.debug.b, 1)
|
||||
utils.graphics.box(x, (y-z) - (self.d), self.w, self.h)
|
||||
love.graphics.setColor(self.debug.r/2, self.debug.g/2, self.debug.b/2, 1)
|
||||
utils.graphics.box(x, (y-z) - (self.d) + (self.h), self.w, self.d)
|
||||
utils.graphics.resetColor()
|
||||
end
|
||||
|
||||
return Hitbox3D
|
|
@ -144,15 +144,30 @@ end
|
|||
|
||||
|
||||
function BaseWorld:getVisibleActors(id)
|
||||
local camx, camy, camw, camh = self.cameras:getViewCoordinate(id)
|
||||
local paddingw = camw * PADDING_VALUE
|
||||
local paddingh = camh * PADDING_VALUE
|
||||
local x = camx - paddingw
|
||||
local y = camy - paddingh
|
||||
local w = camw + paddingw * 2
|
||||
local h = camh + paddingh * 2
|
||||
local actors = {}
|
||||
if (id ~= nil) then
|
||||
local camx, camy, camw, camh = self.cameras:getViewCoordinate(id)
|
||||
local paddingw = camw * PADDING_VALUE
|
||||
local paddingh = camh * PADDING_VALUE
|
||||
local x = camx - paddingw
|
||||
local y = camy - paddingh
|
||||
local w = camw + paddingw * 2
|
||||
local h = camh + paddingh * 2
|
||||
|
||||
return self:getActorsInRect(x, y, w, h)
|
||||
actors = self:getActorsInRect(x, y, w, h)
|
||||
else
|
||||
actors = self:getActors()
|
||||
end
|
||||
|
||||
table.sort(actors, function(a,b)
|
||||
if (a.depth == b.depth) then
|
||||
return a.creationID < b.creationID
|
||||
else
|
||||
return a.depth > b.depth
|
||||
end
|
||||
end)
|
||||
|
||||
return actors
|
||||
end
|
||||
|
||||
-- BODIES MANAGEMENT FUNCTIONS
|
||||
|
@ -426,20 +441,7 @@ function BaseWorld:draw(dt)
|
|||
end
|
||||
|
||||
function BaseWorld:drawActors(id)
|
||||
local actors
|
||||
if (id == nil) then
|
||||
actors = self:getActors()
|
||||
else
|
||||
actors = self:getVisibleActors(id)
|
||||
end
|
||||
|
||||
table.sort(actors, function(a,b)
|
||||
if (a.depth == b.depth) then
|
||||
return a.creationID < b.creationID
|
||||
else
|
||||
return a.depth > b.depth
|
||||
end
|
||||
end)
|
||||
local actors = self:getVisibleActors(id)
|
||||
|
||||
for i,v in ipairs(actors) do
|
||||
v:draw()
|
||||
|
|
|
@ -357,18 +357,19 @@ function CameraSystem:followAllActors(id)
|
|||
if (#self.targets > 0) then
|
||||
local minX, minY, maxX, maxY
|
||||
for i, target in ipairs(self.targets) do
|
||||
local xx, yy = target:getViewCenter()
|
||||
local x, y, w, h = target:getShape()
|
||||
local x2, y2 = x + w, y + h
|
||||
-- If start by initializing the value at the first found value
|
||||
if (minX == nil) then minX = xx - (target.w/2) end
|
||||
if (maxX == nil) then maxX = xx + (target.w/2) end
|
||||
if (minY == nil) then minY = yy - (target.h/2) end
|
||||
if (maxY == nil) then maxY = yy + (target.h/2) end
|
||||
if (minX == nil) then minX = x end
|
||||
if (maxX == nil) then maxX = x2 end
|
||||
if (minY == nil) then minY = y end
|
||||
if (maxY == nil) then maxY = y2 end
|
||||
|
||||
|
||||
minX = math.min(minX, xx - (target.w/2))
|
||||
maxX = math.max(maxX, xx + (target.w/2))
|
||||
minY = math.min(minY, yy - (target.h/2))
|
||||
maxY = math.max(maxY, yy + (target.h/2))
|
||||
minX = math.min(minX, x)
|
||||
maxX = math.max(maxX, x2)
|
||||
minY = math.min(minY, y)
|
||||
maxY = math.max(maxY, y2)
|
||||
end
|
||||
|
||||
-- Add padding
|
||||
|
|
314
gamecore/modules/world/world3D.lua
Normal file
314
gamecore/modules/world/world3D.lua
Normal file
|
@ -0,0 +1,314 @@
|
|||
-- world3D.lua :: a basic fake3D world based on bump-2dpd.
|
||||
|
||||
--[[
|
||||
Copyright © 2019 Kazhnuz
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
]]
|
||||
|
||||
local cwd = (...):gsub('%.world3D$', '') .. "."
|
||||
|
||||
local BaseWorld = require(cwd .. "baseworld")
|
||||
local World3D = BaseWorld:extend()
|
||||
|
||||
local Sti = require(cwd .. "libs.sti")
|
||||
local Bump = require(cwd .. "libs.bump")
|
||||
local Bump3D = require(cwd .. "libs.bump-3dpd")
|
||||
local Tsort = require(cwd .. "libs.tsort")
|
||||
local CameraSystem = require(cwd .. "camera")
|
||||
|
||||
local PADDING_VALUE = 10/100
|
||||
|
||||
function World3D:new(scene, actorlist, mapfile)
|
||||
World3D.super.new(self, scene, actorlist, mapfile)
|
||||
end
|
||||
|
||||
-- ACTORS FUNCTIONS
|
||||
-- Add support for bodies in Actor functions
|
||||
|
||||
function World3D:initActors()
|
||||
self.currentCreationID = 0
|
||||
self.actors = {}
|
||||
self.bodies = Bump3D.newWorld(50)
|
||||
self:initShapes()
|
||||
self:initTerrain()
|
||||
end
|
||||
|
||||
function World3D:newActor(name, x, y, z)
|
||||
self.obj.index[name](self, x, y, z)
|
||||
end
|
||||
|
||||
function World3D:newCollision(name, x, y, z, w, h, d)
|
||||
self.obj.collisions[name](self, x, y, z, w, h, d)
|
||||
end
|
||||
|
||||
function World3D:moveActor(actor, x, y, z, filter)
|
||||
return self.bodies:move(actor.mainHitbox, x, y, z, filter)
|
||||
end
|
||||
|
||||
function World3D:getActorsInRect(x, y, w, h)
|
||||
return self:getShapeInRect(x, y, w, h)
|
||||
end
|
||||
|
||||
function BaseWorld:getVisibleActors(id)
|
||||
local actors = {}
|
||||
if (id ~= nil) then
|
||||
local camx, camy, camw, camh = self.cameras:getViewCoordinate(id)
|
||||
local paddingw = camw * PADDING_VALUE
|
||||
local paddingh = camh * PADDING_VALUE
|
||||
local x = camx - paddingw
|
||||
local y = camy - paddingh
|
||||
local w = camw + paddingw * 2
|
||||
local h = camh + paddingh * 2
|
||||
|
||||
actors = self:getActorsInRect(x, y, w, h)
|
||||
else
|
||||
actors = self:getActors()
|
||||
end
|
||||
|
||||
actors = self:zSortItems(actors)
|
||||
|
||||
return actors
|
||||
end
|
||||
|
||||
|
||||
-- PLAYER FUNCTIONS
|
||||
-- Load player stuff
|
||||
|
||||
function World3D:addPlayer(actor, sourceid, haveCam)
|
||||
local player = {}
|
||||
player.actor = actor
|
||||
player.sourceid = sourceid or 1
|
||||
|
||||
table.insert(self.players, player)
|
||||
|
||||
self.cameras:addTarget(player.actor)
|
||||
end
|
||||
|
||||
-- MAP LOADING FUNCTIONS
|
||||
-- Handle loading of actors from map
|
||||
|
||||
function World3D:batchActor(objectlayer, object)
|
||||
local name = objectlayer.name
|
||||
local gwidth = object.properties.gwidth or self.map.tilewidth
|
||||
local gheight = object.properties.gheight or self.map.tileheight
|
||||
local x = object.x
|
||||
local y = object.y
|
||||
local z = object.properties.z or 0
|
||||
local w = object.width
|
||||
local h = object.height
|
||||
|
||||
local cellHor = math.ceil(w / gwidth)
|
||||
local cellVert = math.ceil(h / gheight)
|
||||
|
||||
for i=1, cellHor do
|
||||
for j=1, cellVert do
|
||||
self:newActor(name, x + (i-1)*gwidth, y + (j-1)*gheight, z)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function World3D:newActorFromMap(objectlayer, object)
|
||||
local z = object.properties.z or 0
|
||||
self:newActor(objectlayer.name, object.x, object.y, z)
|
||||
end
|
||||
|
||||
function World3D:newCollisionFromMap(objectlayer, object)
|
||||
local z = object.properties.z or 0
|
||||
local d = object.properties.d or 16
|
||||
self:newCollision(objectlayer.name, object.x, object.y, z, object.width, object.height, d)
|
||||
end
|
||||
|
||||
function World3D:addPlayerFromMap(object, i)
|
||||
local z = object.properties.z or 0
|
||||
self:addPlayer(self.obj.Player(self, object.x, object.y, z), i)
|
||||
end
|
||||
|
||||
-- BODIES MANAGEMENT FUNCTIONS
|
||||
-- Basic function to handle bodies. Wrappers around Bump2D functions
|
||||
|
||||
function World3D:registerBody(body)
|
||||
return self.bodies:add(body, body.x, body.y, body.z, body.w, body.h, body.d)
|
||||
end
|
||||
|
||||
function World3D:updateBody(body)
|
||||
return self.bodies:update(body, body.x, body.y, body.z, body.w, body.h, body.d)
|
||||
end
|
||||
|
||||
function World3D:removeBody(body)
|
||||
return self.bodies:remove(body)
|
||||
end
|
||||
|
||||
function World3D:checkCollision(body, x, y, z, filter)
|
||||
return self.bodies:check(body, x, y, z, filter)
|
||||
end
|
||||
|
||||
function World3D:getBodiesInRect(x, y, w, h)
|
||||
return {} --self.bodies:queryRect(x, y, w, h)
|
||||
end
|
||||
|
||||
-- UPDATE
|
||||
-- Update everything in the world
|
||||
|
||||
function World3D:updateActors(dt)
|
||||
World3D.super.updateActors(self, dt)
|
||||
local actors = self:getActors()
|
||||
for i,v in ipairs(actors) do
|
||||
v:redrawShadowCanvas()
|
||||
end
|
||||
end
|
||||
|
||||
-- SHAPE SYSTEM
|
||||
-- Handle onscreen shapes
|
||||
|
||||
function World3D:initShapes()
|
||||
self.shapes = Bump.newWorld(50)
|
||||
end
|
||||
|
||||
function World3D:registerShape(actor)
|
||||
local x, y, w, h = actor:getShape()
|
||||
return self.shapes:add(actor, x, y, w, h)
|
||||
end
|
||||
|
||||
function World3D:updateShape(actor)
|
||||
local x, y, w, h = actor:getShape()
|
||||
return self.shapes:update(actor, x, y, w, h)
|
||||
end
|
||||
|
||||
function World3D:removeShape(actor)
|
||||
return self.shapes:remove(actor)
|
||||
end
|
||||
|
||||
function World3D:checkShapeIntersection(actor, x, y)
|
||||
return self.shapes:check(actor, x, y)
|
||||
end
|
||||
|
||||
function World3D:getShapeInRect(x, y, w, h)
|
||||
return self.shapes:queryRect(x, y, w, h)
|
||||
end
|
||||
|
||||
-- TERRAIN SYSTEM
|
||||
-- Handle onscreen shapes
|
||||
|
||||
function World3D:initTerrain()
|
||||
self.terrains = Bump.newWorld(50)
|
||||
end
|
||||
|
||||
function World3D:registerTerrain(actor)
|
||||
return self.terrains:add(actor, actor.x, actor.y, actor.w, actor.h)
|
||||
end
|
||||
|
||||
function World3D:updateTerrain(actor)
|
||||
return self.terrains:update(actor, actor.x, actor.y, actor.w, actor.h)
|
||||
end
|
||||
|
||||
function World3D:removeTerrain(actor)
|
||||
return self.terrains:remove(actor)
|
||||
end
|
||||
|
||||
function World3D:getTerrainInRect(x, y, w, h)
|
||||
return self.terrains:queryRect(x, y, w, h)
|
||||
end
|
||||
|
||||
-- DRAW FUNCTIONS
|
||||
-- Functions to draw the world
|
||||
|
||||
function World3D:zSortItems(items)
|
||||
-- zSorting algorithm taken from bump3D example, adapted to gamecore.
|
||||
local graph = Tsort.new()
|
||||
local noOverlap = {}
|
||||
|
||||
-- Iterate through all visible items, and calculate ordering of all pairs
|
||||
-- of overlapping items.
|
||||
-- TODO: Each pair is calculated twice currently. Maybe this is slow?
|
||||
for _, itemA in ipairs(items) do repeat
|
||||
local x, y, w, h = self.shapes:getRect(itemA)
|
||||
local otherItemsFilter = function(other) return other ~= itemA end
|
||||
local overlapping, len = self.shapes:queryRect(x, y, w, h, otherItemsFilter)
|
||||
|
||||
if len == 0 then
|
||||
table.insert(noOverlap, itemA)
|
||||
|
||||
break
|
||||
end
|
||||
|
||||
local _, aY, aZ, _, aH, aD = self.bodies:getCube(itemA.mainHitbox)
|
||||
aDepth = itemA.depth
|
||||
aID = itemA.id
|
||||
aType = itemA.type
|
||||
aZ = math.ceil(aZ)
|
||||
aY = math.ceil(aY)
|
||||
|
||||
for _, itemB in ipairs(overlapping) do
|
||||
local _, bY, bZ, _, bH, bD = self.bodies:getCube(itemB.mainHitbox)
|
||||
bDepth = itemB.depth
|
||||
bID = itemB.id
|
||||
bType = itemB.type
|
||||
bZ = math.ceil(bZ)
|
||||
bY = math.ceil(bY)
|
||||
|
||||
if aZ >= bZ + bD then
|
||||
-- item A is completely above item B
|
||||
graph:add(itemB, itemA)
|
||||
elseif bZ >= aZ + aD then
|
||||
-- item B is completely above item A
|
||||
graph:add(itemA, itemB)
|
||||
elseif aY + aH <= bY then
|
||||
-- item A is completely behind item B
|
||||
graph:add(itemA, itemB)
|
||||
elseif bY + bH <= aY then
|
||||
-- item B is completely behind item A
|
||||
graph:add(itemB, itemA)
|
||||
elseif (aY - aZ) + aH > (bY - bZ) + bH then
|
||||
-- item A's forward-most point is in front of item B's forward-most point
|
||||
graph:add(itemB, itemA)
|
||||
elseif (aY - aZ) + aH < (bY - bZ) + bH then
|
||||
-- item B's forward-most point is in front of item A's forward-most point
|
||||
graph:add(itemA, itemB)
|
||||
else
|
||||
-- item A's forward-most point is the same than item B's forward-most point
|
||||
if aDepth > bDepth then
|
||||
graph:add(itemB, itemA)
|
||||
elseif aDepth < bDepth then
|
||||
graph:add(itemA, itemB)
|
||||
else
|
||||
if aID > bID then
|
||||
graph:add(itemA, itemB)
|
||||
elseif aID < bID then
|
||||
graph:add(itemB, itemA)
|
||||
else
|
||||
err("two object can't have the same ID")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
until true end
|
||||
|
||||
local sorted, err = graph:sort()
|
||||
if err then
|
||||
error(err)
|
||||
end
|
||||
for _, item in ipairs(noOverlap) do
|
||||
table.insert(sorted, item)
|
||||
end
|
||||
|
||||
return sorted
|
||||
|
||||
end
|
||||
|
||||
return World3D
|
Loading…
Reference in a new issue