add game files
This commit is contained in:
parent
d92247535f
commit
b829b49acb
|
@ -5,3 +5,7 @@ install
|
|||
TODO.txt
|
||||
.cache
|
||||
compile_flags.txt
|
||||
game/shader
|
||||
game/*.dll
|
||||
game/*.dll.a
|
||||
game/*.exe
|
|
@ -0,0 +1,4 @@
|
|||
WindowWidth = 1024
|
||||
WindowHeight = 720
|
||||
Title = "InfiniteShoot - VisualGMQ For 1MGames v0.1.0"
|
||||
EntryFile = "main.lua"
|
|
@ -0,0 +1,50 @@
|
|||
local _M = {}
|
||||
|
||||
_M.TileSize = 32
|
||||
_M.PlayerInfo = {
|
||||
velocity = 250,
|
||||
hp = 100,
|
||||
}
|
||||
_M.MonsterInfo = {
|
||||
velocity = 100,
|
||||
hp = 50,
|
||||
damage = 10,
|
||||
}
|
||||
_M.RoleColliBox = {
|
||||
w = 14,
|
||||
h = 32,
|
||||
x = 9,
|
||||
y = 0,
|
||||
}
|
||||
_M.Invincible = 1
|
||||
_M.BulletColliBox = {
|
||||
x = 10,
|
||||
y = 0,
|
||||
w = 12,
|
||||
h = 12,
|
||||
}
|
||||
_M.StonePutProbability = 0.1
|
||||
_M.PlayerHpBarInfo = {
|
||||
width = _M.TileSize,
|
||||
height = 5,
|
||||
}
|
||||
_M.MonsetHpBarInfo= {
|
||||
width = _M.TileSize,
|
||||
height = 5,
|
||||
}
|
||||
_M.GunInfo = {
|
||||
cooldown = 0.1
|
||||
}
|
||||
_M.BulletInfo = {
|
||||
damage = 10,
|
||||
velocity = 500,
|
||||
}
|
||||
_M.GunInfo = {
|
||||
cooldown = 0.1
|
||||
}
|
||||
_M.BulletInfo = {
|
||||
damage = 10,
|
||||
velocity = 500,
|
||||
}
|
||||
|
||||
return _M
|
|
@ -0,0 +1,19 @@
|
|||
---@class Content
|
||||
local _M = {}
|
||||
|
||||
---@type Texture
|
||||
_M.Texture = nil
|
||||
|
||||
---@type TileSheet
|
||||
_M.Tilesheet = nil
|
||||
|
||||
---@type Entity
|
||||
_M.PlayerEntity = nil
|
||||
|
||||
---@type table<Entity>
|
||||
_M.BulletList = {}
|
||||
|
||||
---@type table<Entity>
|
||||
_M.MonsterList = {}
|
||||
|
||||
return _M
|
|
@ -0,0 +1,475 @@
|
|||
local hazel = require "hazel"
|
||||
local constants = require "constants"
|
||||
local math = require "math"
|
||||
local vmath = require "vmath"
|
||||
local content = require "content"
|
||||
|
||||
---@class ECS
|
||||
local _M = {}
|
||||
|
||||
---@class Entity
|
||||
---@field name string
|
||||
---@field component table<Component>
|
||||
local Entity = { name = "", components = {}}
|
||||
|
||||
---@param component Component
|
||||
function Entity.SetComponent(self, component)
|
||||
if not component then
|
||||
return
|
||||
end
|
||||
---@type Component
|
||||
local oldComp = self.components[component:GetName()]
|
||||
if oldComp then
|
||||
oldComp.parent = nil
|
||||
hazel.Log.Logw(string.format("component %s already exists, replace it", oldComp:GetName()))
|
||||
end
|
||||
component.parent = self
|
||||
self.components[component:GetName()] = component
|
||||
end
|
||||
|
||||
---@return Component|nil
|
||||
---@param type string
|
||||
function Entity.GetComponent(self, type)
|
||||
if not type then
|
||||
return nil
|
||||
end
|
||||
return self.components[type]
|
||||
end
|
||||
|
||||
---@param type string
|
||||
function Entity.RemoveComponent(self, type)
|
||||
self.components[type] = nil
|
||||
end
|
||||
|
||||
_M.Entity = Entity
|
||||
|
||||
---@return Entity
|
||||
---@param name string
|
||||
function _M.CreateEntity(name)
|
||||
local o = {name = name, components = {}}
|
||||
setmetatable(o, {__index = Entity})
|
||||
return o
|
||||
end
|
||||
|
||||
---@param self Entity
|
||||
function Entity.Update(self)
|
||||
---@param v Component
|
||||
for _, v in pairs(self.components) do
|
||||
if v:IsActive() and v.Update then
|
||||
v:Update()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---@class Component
|
||||
local Component = {
|
||||
---@param self Component
|
||||
---@return boolean
|
||||
IsActive = function(self)
|
||||
return self.isActive
|
||||
end,
|
||||
|
||||
---@param self Component
|
||||
Disable = function(self)
|
||||
self.isActive = false
|
||||
end,
|
||||
|
||||
---@param self Component
|
||||
Enable = function(self)
|
||||
self.isActive = true
|
||||
end,
|
||||
|
||||
---@param self Component
|
||||
---@return string
|
||||
GetName = function(self)
|
||||
return self.name
|
||||
end,
|
||||
|
||||
---@param self Component
|
||||
---@return Entity
|
||||
GetParent = function(self)
|
||||
return self.parent
|
||||
end,
|
||||
}
|
||||
|
||||
---@return Component
|
||||
function _M.CreateComponent(o)
|
||||
local o = o or {}
|
||||
setmetatable(o , {__index = Component})
|
||||
return o
|
||||
end
|
||||
|
||||
---@class ComponentType
|
||||
local ComponentType = {
|
||||
Transform = "Transform",
|
||||
Image = "Image",
|
||||
Controller = "Controller",
|
||||
RoleProp = "RoleProp",
|
||||
HpShow = "HpShow",
|
||||
Gun = "Gun",
|
||||
Bullet = "Bullet",
|
||||
Direction = "Direction",
|
||||
AI = "AI",
|
||||
ColliBox = "ColliBox",
|
||||
Invincible = "Invincible",
|
||||
}
|
||||
|
||||
_M.ComponentType = ComponentType
|
||||
|
||||
---@class TransformComponent:Component
|
||||
---@field position Point
|
||||
---@field size Point
|
||||
---@field flip number
|
||||
|
||||
---@return TransformComponent
|
||||
---@param pos Point
|
||||
---@param size Point
|
||||
---@param flip number|nil
|
||||
function _M.CreateTransformComponent(pos, size, flip)
|
||||
local o = { isActive = true, name = ComponentType.Transform, position = pos, size = size, flip = flip or Flip.None, parent = nil }
|
||||
o.Update = function () end
|
||||
return _M.CreateComponent(o)
|
||||
end
|
||||
|
||||
---@class ImageComponent:Component
|
||||
---@field tilesheet TileSheet
|
||||
---@field row number
|
||||
---@field col number
|
||||
|
||||
---@return ImageComponent
|
||||
---@param tilesheet TileSheet
|
||||
---@param col number
|
||||
---@param row number
|
||||
function _M.CreateImageComponent(tilesheet, col, row)
|
||||
local o = { isActive = true, name = ComponentType.Image, tilesheet = tilesheet, col = col, row = row, parent = nil }
|
||||
|
||||
---@param self ImageComponent
|
||||
o.Update = function(self)
|
||||
---@type TransformComponent
|
||||
local transform = self:GetParent():GetComponent(ComponentType.Transform)
|
||||
if tilesheet then
|
||||
tilesheet:Draw(self.col or 0, self.row or 0,
|
||||
hazel.CreateRect(transform.position.x, transform.position.y, transform.size.x, transform.size.y),
|
||||
transform.flip)
|
||||
end
|
||||
end
|
||||
|
||||
return _M.CreateComponent(o)
|
||||
end
|
||||
|
||||
---@class DirectionComponent:Component
|
||||
---@field direction Point
|
||||
|
||||
function _M.CreateDirectionComponent(startRow)
|
||||
local o = { isActive = true, name = ComponentType.Direction, direction = hazel.CreatePos(0, 0), startRow = startRow, parent = nil }
|
||||
|
||||
---@param self DirectionComponent
|
||||
---@param dir Point
|
||||
o.SetDir = function(self, dir)
|
||||
self.direction = dir
|
||||
end
|
||||
|
||||
---@param self DirectionComponent
|
||||
o.Update = function(self)
|
||||
local image = self:GetParent():GetComponent(ComponentType.Image)
|
||||
if not image then
|
||||
return
|
||||
end
|
||||
|
||||
local absX = math.abs(self.direction.x)
|
||||
local absY = math.abs(self.direction.y)
|
||||
if self.direction.y <= 0 and absX <= absY then
|
||||
image.col = 0
|
||||
image.row = 1 + self.startRow
|
||||
end
|
||||
if self.direction.y > 0 and absX <= absY then
|
||||
image.col = 0
|
||||
image.row = 0 + self.startRow
|
||||
end
|
||||
if self.direction.x < 0 and absY < absX then
|
||||
image.col = 0
|
||||
image.row = 2 + self.startRow
|
||||
end
|
||||
if self.direction.x > 0 and absY < absX then
|
||||
image.col = 0
|
||||
image.row = 3 + self.startRow
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
return _M.CreateComponent(o)
|
||||
end
|
||||
|
||||
---@class ControllerComponent:Component
|
||||
|
||||
---@return ControllerComponent
|
||||
---@param speed number
|
||||
function _M.CreateControllerComponent()
|
||||
local o = { isActive = true, name = ComponentType.Controller, parent = nil }
|
||||
|
||||
---@param self ControllerComponent
|
||||
o.Update = function(self)
|
||||
---@type RolePropComponent
|
||||
local roleProp = self:GetParent():GetComponent(ComponentType.RoleProp)
|
||||
local speed = roleProp.speed
|
||||
|
||||
---@type TransformComponent
|
||||
local transform = self:GetParent():GetComponent(ComponentType.Transform)
|
||||
local elapseTime = hazel.Time.GetElapseTime()
|
||||
if hazel.IsKeyPressing(hazel.Key.A) then
|
||||
transform.position.x = transform.position.x - speed * elapseTime
|
||||
end
|
||||
if hazel.IsKeyPressing(hazel.Key.D) then
|
||||
transform.position.x = transform.position.x + speed * elapseTime
|
||||
end
|
||||
if hazel.IsKeyPressing(hazel.Key.W) then
|
||||
transform.position.y = transform.position.y - speed * elapseTime
|
||||
end
|
||||
if hazel.IsKeyPressing(hazel.Key.S) then
|
||||
transform.position.y = transform.position.y + speed * elapseTime
|
||||
end
|
||||
|
||||
---@type Point
|
||||
local mousePos = hazel.GetGameMousePos()
|
||||
|
||||
local playerCenterX = transform.position.x
|
||||
local playerCenterY = transform.position.y
|
||||
playerCenterX = playerCenterX + constants.TileSize / 2
|
||||
playerCenterY = playerCenterY + constants.TileSize / 2
|
||||
---@type Point
|
||||
local mouseDir = hazel.CreatePos(mousePos.x - playerCenterX, mousePos.y - playerCenterY)
|
||||
self:GetParent():GetComponent(ComponentType.Direction):SetDir(mouseDir)
|
||||
end
|
||||
|
||||
return _M.CreateComponent(o)
|
||||
end
|
||||
|
||||
---@class InvincibleComponent:Component
|
||||
---@field time number
|
||||
|
||||
---@return InvincibleComponent
|
||||
---@param time number
|
||||
function _M.CreateInvincibleComponent(time)
|
||||
local o = { isActive = true, name = ComponentType.Invincible, cooldown = time, timeCountDown = time, parent = nil }
|
||||
|
||||
---@return boolean
|
||||
---@param self InvincibleComponent
|
||||
o.IsInvincibleState = function(self)
|
||||
return self.timeCountDown > 0
|
||||
end
|
||||
|
||||
---@param self InvincibleComponent
|
||||
o.IntoInvincible = function(self)
|
||||
if self.timeCountDown <= 0 then
|
||||
self.timeCountDown = self.cooldown
|
||||
end
|
||||
end
|
||||
|
||||
---@param self InvincibleComponent
|
||||
o.Update = function(self)
|
||||
self.timeCountDown = self.timeCountDown - hazel.Time.GetElapseTime()
|
||||
if self.timeCountDown < 0 then
|
||||
self.timeCountDown = 0
|
||||
end
|
||||
end
|
||||
|
||||
return _M.CreateComponent(o)
|
||||
end
|
||||
|
||||
---@class RolePropComponent:Component
|
||||
---@field hp number
|
||||
---@field maxHp number
|
||||
---@field speed number
|
||||
---@field damage number
|
||||
|
||||
---@return RolePropComponent
|
||||
---@param hp number
|
||||
---@param speed number
|
||||
---@param damage number|nil
|
||||
function _M.CreateRolePropComponent(hp, speed, damage)
|
||||
local o = { isActive = true, name = ComponentType.RoleProp, maxHp = hp, hp = hp, speed = speed, damage = damage or 0, parent = nil }
|
||||
---@param self RolePropComponent
|
||||
o.IsDie = function(self)
|
||||
return self.hp <= 0
|
||||
end
|
||||
o.Update = function(self)
|
||||
if self.hp < 0 then
|
||||
self.hp = 0
|
||||
end
|
||||
end
|
||||
return _M.CreateComponent(o)
|
||||
end
|
||||
|
||||
---@class HpShowComponent:Component
|
||||
---@field size Point
|
||||
|
||||
---@return HpShowComponent
|
||||
---@param size Point
|
||||
function _M.CreateHpShowComponent(size)
|
||||
local o = { isActive = true, name = ComponentType.HpShow, size = size, parent = nil }
|
||||
|
||||
---@param self HpShowComponent
|
||||
o.Update = function(self)
|
||||
---@type Point
|
||||
local position = self:GetParent():GetComponent(ComponentType.Transform).position
|
||||
local pos = hazel.CreatePos(position.x, position.y - self.size.y - 2)
|
||||
|
||||
---@type RolePropComponent
|
||||
local roleProp = self:GetParent():GetComponent(ComponentType.RoleProp)
|
||||
hazel.Renderer.SetDrawColor(1, 1, 1, 1)
|
||||
hazel.Renderer.FillRect(pos.x, pos.y, size.x, size.y)
|
||||
|
||||
hazel.Renderer.SetDrawColor(0, 1, 0, 1)
|
||||
hazel.Renderer.FillRect(pos.x, pos.y, size.x * roleProp.hp / roleProp.maxHp, size.y)
|
||||
|
||||
hazel.Renderer.SetDrawColor(0, 0, 0, 1)
|
||||
hazel.Renderer.DrawRect(pos.x, pos.y, size.x, size.y)
|
||||
end
|
||||
return _M.CreateComponent(o)
|
||||
end
|
||||
|
||||
|
||||
---@class AIComponent:Component
|
||||
|
||||
---@return AIComponent
|
||||
function _M.CreateAIComponent()
|
||||
local o = { isActive = true, name = ComponentType.AI, parent = nil }
|
||||
|
||||
---@param self AIComponent
|
||||
o.Update = function(self)
|
||||
---@type DirectionComponent
|
||||
local direction = self:GetParent():GetComponent(ComponentType.Direction)
|
||||
|
||||
local playerCenterX = content.PlayerEntity:GetComponent(ComponentType.Transform).position.x + constants.TileSize / 2
|
||||
local playerCenterY = content.PlayerEntity:GetComponent(ComponentType.Transform).position.y + constants.TileSize / 2
|
||||
local myselfCenterX = self:GetParent():GetComponent(ComponentType.Transform).position.x + constants.TileSize / 2
|
||||
local myselfCenterY = self:GetParent():GetComponent(ComponentType.Transform).position.y + constants.TileSize / 2
|
||||
|
||||
---@type Point
|
||||
local dir = vmath.Normalize(hazel.CreatePos(playerCenterX - myselfCenterX, playerCenterY - myselfCenterY))
|
||||
direction:SetDir(dir)
|
||||
|
||||
---@type Point
|
||||
local position = self:GetParent():GetComponent(ComponentType.Transform).position
|
||||
local velocity = self:GetParent():GetComponent(ComponentType.RoleProp).speed
|
||||
local elapseTime = hazel.Time.GetElapseTime()
|
||||
position.x = position.x + velocity * dir.x * elapseTime
|
||||
position.y = position.y + velocity * dir.y * elapseTime
|
||||
end
|
||||
|
||||
return _M.CreateComponent(o)
|
||||
end
|
||||
|
||||
---@class GunComponent:Component
|
||||
---@field damage number
|
||||
---@field speed Point
|
||||
|
||||
---@return GunComponent
|
||||
---@param damage number
|
||||
---@param velocity number
|
||||
function _M.CreateGunComponent(damage, velocity)
|
||||
local o = { isActive = true, name = ComponentType.Gun, damage = damage, timeCounter = 0, parent = nil }
|
||||
---@param self GunComponent
|
||||
o.Update = function(self)
|
||||
if self.timeCounter < constants.GunInfo.cooldown then
|
||||
self.timeCounter = self.timeCounter + hazel.Time.GetElapseTime()
|
||||
end
|
||||
if self.timeCounter >= constants.GunInfo.cooldown then
|
||||
self.timeCounter = constants.GunInfo.cooldown
|
||||
end
|
||||
if hazel.GetMouseButtonState(hazel.MouseButton.Left) == hazel.InputState.Press and self.timeCounter >= constants.GunInfo.cooldown then
|
||||
self.timeCounter = self.timeCounter - constants.GunInfo.cooldown
|
||||
---@type Point
|
||||
local position = self:GetParent():GetComponent(ComponentType.Transform).position
|
||||
---@type Point
|
||||
local mousePos = hazel.GetGameMousePos()
|
||||
local playerCenterX = position.x + constants.TileSize / 2
|
||||
local playerCenterY = position.y + constants.TileSize / 2
|
||||
local nMouseDir = vmath.Normalize(hazel.CreatePos(mousePos.x - playerCenterX, mousePos.y - playerCenterY))
|
||||
|
||||
local bullet = _M.CreateBullet(hazel.CreatePos(playerCenterX - constants.TileSize / 2, playerCenterY - constants.TileSize / 2), self.damage, hazel.CreatePos(nMouseDir.x * velocity, nMouseDir.y * velocity))
|
||||
table.insert(content.BulletList, bullet)
|
||||
end
|
||||
end
|
||||
return _M.CreateComponent(o)
|
||||
end
|
||||
|
||||
|
||||
|
||||
---@class BulletComponent:Component
|
||||
---@field damage number
|
||||
---@field speed Point
|
||||
|
||||
---@return BulletComponent
|
||||
---@param damage number
|
||||
---@param speed Point
|
||||
function _M.CreateBulletComponent(damage, speed)
|
||||
local o = { isActive = true, name = ComponentType.Bullet, damage = damage, speed = speed, parent = nil }
|
||||
---@param self BulletComponent
|
||||
o.Update = function(self)
|
||||
local position = self:GetParent():GetComponent(ComponentType.Transform).position
|
||||
local elapseTime = hazel.Time.GetElapseTime()
|
||||
position.x = position.x + self.speed.x * elapseTime
|
||||
position.y = position.y + self.speed.y * elapseTime
|
||||
end
|
||||
return _M.CreateComponent(o)
|
||||
end
|
||||
|
||||
---@class ColliBoxComponent:Component
|
||||
---@field rect Rect
|
||||
|
||||
---@return ColliBoxComponent
|
||||
---@param rect Rect
|
||||
function _M.CreateColliBoxComponent(rect)
|
||||
local o = { isActive = true, name = ComponentType.ColliBox, rect = rect, parent = nil }
|
||||
o.Update = function(self) end
|
||||
return _M.CreateComponent(o)
|
||||
end
|
||||
|
||||
|
||||
---@return Entity
|
||||
---@param pos Point
|
||||
---@param damage number
|
||||
---@param speed Point
|
||||
function _M.CreateBullet(pos, damage, speed)
|
||||
---@type Entity
|
||||
local entity = _M.CreateEntity("Bullet")
|
||||
entity:SetComponent(_M.CreateTransformComponent(pos, hazel.CreateSize(constants.TileSize, constants.TileSize)))
|
||||
entity:SetComponent(_M.CreateBulletComponent(damage, speed))
|
||||
entity:SetComponent(_M.CreateImageComponent(content.Tilesheet, 1, 4))
|
||||
entity:SetComponent(_M.CreateColliBoxComponent(constants.BulletColliBox))
|
||||
return entity
|
||||
end
|
||||
|
||||
---@return Entity
|
||||
---@param pos Point
|
||||
function _M.CreatePlayer(pos)
|
||||
local entity = _M.CreateEntity("player")
|
||||
entity:SetComponent(_M.CreateTransformComponent(hazel.CreatePos(pos.x, pos.y), hazel.CreateSize(constants.TileSize, constants.TileSize), Flip.Vertical))
|
||||
entity:SetComponent(_M.CreateImageComponent(content.Tilesheet, 0, 0))
|
||||
entity:SetComponent(_M.CreateControllerComponent())
|
||||
entity:SetComponent(_M.CreateRolePropComponent(constants.PlayerInfo.hp, constants.PlayerInfo.velocity))
|
||||
entity:SetComponent(_M.CreateHpShowComponent(hazel.CreateSize(constants.PlayerHpBarInfo.width, constants.PlayerHpBarInfo.height)))
|
||||
entity:SetComponent(_M.CreateGunComponent(constants.BulletInfo.damage, constants.BulletInfo.velocity))
|
||||
entity:SetComponent(_M.CreateDirectionComponent(0))
|
||||
entity:SetComponent(_M.CreateColliBoxComponent(constants.RoleColliBox))
|
||||
entity:SetComponent(_M.CreateInvincibleComponent(constants.Invincible))
|
||||
return entity
|
||||
end
|
||||
|
||||
---@return Entity
|
||||
---@param pos Point
|
||||
function _M.CreateMonster(pos)
|
||||
local entity = _M.CreateEntity("monster")
|
||||
entity:SetComponent(_M.CreateTransformComponent(hazel.CreatePos(pos.x, pos.y), hazel.CreateSize(constants.TileSize, constants.TileSize), Flip.Vertical))
|
||||
entity:SetComponent(_M.CreateImageComponent(content.Tilesheet, 0, 5))
|
||||
entity:SetComponent(_M.CreateRolePropComponent(constants.MonsterInfo.hp, constants.MonsterInfo.velocity, constants.MonsterInfo.damage))
|
||||
entity:SetComponent(_M.CreateHpShowComponent(hazel.CreateSize(constants.MonsetHpBarInfo.width, constants.MonsetHpBarInfo.height)))
|
||||
entity:SetComponent(_M.CreateDirectionComponent(5))
|
||||
entity:SetComponent(_M.CreateColliBoxComponent(constants.RoleColliBox))
|
||||
entity:SetComponent(_M.CreateAIComponent())
|
||||
return entity
|
||||
end
|
||||
|
||||
|
||||
return _M
|
|
@ -0,0 +1,465 @@
|
|||
---@class libhazel
|
||||
local libhazel = require "libhazel"
|
||||
|
||||
---@class hazel
|
||||
local _M = {}
|
||||
|
||||
---@class Point
|
||||
---@field x number
|
||||
---@field y number
|
||||
|
||||
---@class Rect
|
||||
---@field x number
|
||||
---@field y number
|
||||
---@field w number
|
||||
---@field h number
|
||||
|
||||
|
||||
---@return Point
|
||||
---@param x number
|
||||
---@param y number
|
||||
function _M.CreatePos(x, y)
|
||||
return {x = x, y = y}
|
||||
end
|
||||
|
||||
---@return Point
|
||||
---@param w number
|
||||
---@param h number
|
||||
function _M.CreateSize(w, h)
|
||||
return {x = w, y = h}
|
||||
end
|
||||
|
||||
|
||||
---@return Rect
|
||||
---@param x number
|
||||
---@param y number
|
||||
---@param w number
|
||||
---@param h number
|
||||
function _M.CreateRect(x, y, w, h)
|
||||
return {x = x, y = y, w = w, h = h}
|
||||
end
|
||||
|
||||
---@class InputState
|
||||
_M.InputState = {
|
||||
Release = 0,
|
||||
Press = 1,
|
||||
Repeat = 2,
|
||||
}
|
||||
|
||||
---@class Key
|
||||
_M.Key = {
|
||||
Unkown = -1,
|
||||
Space = 32,
|
||||
Apostrophe = 39,
|
||||
Comma = 44,
|
||||
Minus = 45,
|
||||
Period = 46,
|
||||
Slash = 47,
|
||||
K_0 = 48,
|
||||
K_1 = 49,
|
||||
K_2 = 50,
|
||||
K_3 = 51,
|
||||
K_4 = 52,
|
||||
K_5 = 53,
|
||||
K_6 = 54,
|
||||
K_7 = 55,
|
||||
K_8 = 56,
|
||||
K_9 = 57,
|
||||
Semicolon = 59,
|
||||
Equal = 61,
|
||||
A = 65,
|
||||
B = 66,
|
||||
C = 67,
|
||||
D = 68,
|
||||
E = 69,
|
||||
F = 70,
|
||||
G = 71,
|
||||
H = 72,
|
||||
I = 73,
|
||||
J = 74,
|
||||
K = 75,
|
||||
L = 76,
|
||||
M = 77,
|
||||
N = 78,
|
||||
O = 79,
|
||||
P = 80,
|
||||
Q = 81,
|
||||
R = 82,
|
||||
S = 83,
|
||||
T = 84,
|
||||
U = 85,
|
||||
V = 86,
|
||||
W = 87,
|
||||
X = 88,
|
||||
Y = 89,
|
||||
Z = 90,
|
||||
Left_bracket = 91,
|
||||
Backslash = 92,
|
||||
Right_bracket = 93,
|
||||
Grave_accent = 96,
|
||||
World_1 = 161,
|
||||
World_2 = 162,
|
||||
Escape = 256,
|
||||
Enter = 257,
|
||||
Tab = 258,
|
||||
Backspace = 259,
|
||||
Insert = 260,
|
||||
Delete = 261,
|
||||
Right = 262,
|
||||
Left = 263,
|
||||
Down = 264,
|
||||
Up = 265,
|
||||
Page_up = 266,
|
||||
Page_down = 267,
|
||||
Home = 268,
|
||||
End = 269,
|
||||
Caps_lock = 280,
|
||||
Scroll_lock = 281,
|
||||
Num_lock = 282,
|
||||
Print_screen = 283,
|
||||
Pause = 284,
|
||||
F1 = 290,
|
||||
F2 = 291,
|
||||
F3 = 292,
|
||||
F4 = 293,
|
||||
F5 = 294,
|
||||
F6 = 295,
|
||||
F7 = 296,
|
||||
F8 = 297,
|
||||
F9 = 298,
|
||||
F10 = 299,
|
||||
F11 = 300,
|
||||
F12 = 301,
|
||||
F13 = 302,
|
||||
F14 = 303,
|
||||
F15 = 304,
|
||||
F16 = 305,
|
||||
F17 = 306,
|
||||
F18 = 307,
|
||||
F19 = 308,
|
||||
F20 = 309,
|
||||
F21 = 310,
|
||||
F22 = 311,
|
||||
F23 = 312,
|
||||
F24 = 313,
|
||||
F25 = 314,
|
||||
KP_0 = 320,
|
||||
KP_1 = 321,
|
||||
KP_2 = 322,
|
||||
KP_3 = 323,
|
||||
KP_4 = 324,
|
||||
KP_5 = 325,
|
||||
KP_6 = 326,
|
||||
KP_7 = 327,
|
||||
KP_8 = 328,
|
||||
KP_9 = 329,
|
||||
KP_decimal = 330,
|
||||
KP_divide = 331,
|
||||
KP_multiply = 332,
|
||||
KP_subtract = 333,
|
||||
KP_add = 334,
|
||||
KP_enter = 335,
|
||||
KP_equal = 336,
|
||||
LeftShift = 340,
|
||||
LeftControl = 341,
|
||||
LeftAlt = 342,
|
||||
LeftSuper = 343,
|
||||
RightShift = 344,
|
||||
RightControl = 345,
|
||||
RightAlt = 346,
|
||||
RightSuper = 347,
|
||||
Menu = 348,
|
||||
}
|
||||
|
||||
---@class MouseButton
|
||||
_M.MouseButton = {
|
||||
Left = 0,
|
||||
Right = 1,
|
||||
Middle = 2,
|
||||
}
|
||||
|
||||
---@return InputState
|
||||
---@param key Key
|
||||
function _M.GetKeyState(key)
|
||||
return libhazel.GetKeyState(key)
|
||||
end
|
||||
|
||||
---@return boolean
|
||||
---@param key number
|
||||
function _M.IsKeyPressing(key)
|
||||
return _M.GetKeyState(key) == _M.InputState.Press
|
||||
end
|
||||
|
||||
---@return boolean
|
||||
---@param key number
|
||||
function _M.IsKeyReleasing(key)
|
||||
return _M.GetKeyState(key) == _M.InputState.Release
|
||||
end
|
||||
|
||||
---@return Point
|
||||
function _M.GetMousePos()
|
||||
local x, y = libhazel.GetMousePos()
|
||||
return _M.CreatePos(x, y)
|
||||
end
|
||||
|
||||
---@return Point
|
||||
function _M.GetGameMousePos()
|
||||
local x, y = libhazel.GetMousePos()
|
||||
local windowSize = _M.GetWindowSize()
|
||||
local canvaSize = _M.GetCanvaSize()
|
||||
return _M.CreatePos(x * canvaSize.x / windowSize.x, y * canvaSize.y / windowSize.y)
|
||||
end
|
||||
|
||||
function _M.HideCursor()
|
||||
libhazel.HideCursor()
|
||||
end
|
||||
|
||||
function _M.ShowCursor()
|
||||
libhazel.ShowCursor()
|
||||
end
|
||||
|
||||
---@return InputState
|
||||
---@param btn MouseButton
|
||||
function _M.GetMouseButtonState(btn)
|
||||
return libhazel.GetMouseButtonState(btn)
|
||||
end
|
||||
|
||||
---@return number
|
||||
function _M.GetTime()
|
||||
return libhazel.GetTime()
|
||||
end
|
||||
|
||||
---@param filename string
|
||||
function _M.SetWindowIcon(filename)
|
||||
libhazel.WindowSetIcon(filename)
|
||||
end
|
||||
|
||||
---@return Point
|
||||
function _M.GetCanvaSize()
|
||||
local x, y = libhazel.GetCanvaSize()
|
||||
return _M.CreatePos(x, y)
|
||||
end
|
||||
|
||||
---@return Point
|
||||
function _M.GetWindowSize()
|
||||
local x, y = libhazel.GetWindowSize()
|
||||
return _M.CreatePos(x, y)
|
||||
end
|
||||
|
||||
---@class Texture
|
||||
---@field w number
|
||||
---@field h number
|
||||
|
||||
---@return Texture
|
||||
---@param filename string
|
||||
function _M.LoadTexture(filename)
|
||||
local texture = libhazel.LoadTexture(filename)
|
||||
local w, h = libhazel.TextureGetSize(texture)
|
||||
return {rawPointer = texture, w = w, h = h}
|
||||
end
|
||||
|
||||
---@param texture Texture
|
||||
function _M.DestroyTexture(texture)
|
||||
libhazel.DestroyTexture(texture.rawPointer)
|
||||
end
|
||||
|
||||
---@return Point
|
||||
---@param texture Texture
|
||||
function _M.GetTextureSize(texture)
|
||||
local x, y = libhazel.TextureGetSize(texture)
|
||||
return _M.CreatePos(x, y)
|
||||
end
|
||||
|
||||
function _M.SayHello()
|
||||
libhazel.SayHello()
|
||||
end
|
||||
|
||||
---@class Flip
|
||||
Flip = {
|
||||
None = 0,
|
||||
Vertical = 1,
|
||||
Horizontal = 2,
|
||||
Both = 3,
|
||||
}
|
||||
|
||||
_M.Flip = Flip
|
||||
|
||||
---@class Renderer
|
||||
local Renderer = {
|
||||
---@param r number
|
||||
---@param g number
|
||||
---@param b number
|
||||
---@param a number
|
||||
SetClearColor = function(r, g, b, a)
|
||||
libhazel.RenderSetClearColor(r, g, b, a or 1)
|
||||
end,
|
||||
|
||||
---@param r number
|
||||
---@param g number
|
||||
---@param b number
|
||||
---@param a number
|
||||
SetDrawColor = function(r, g, b, a)
|
||||
libhazel.RenderSetDrawColor(r, g, b, a or 1)
|
||||
end,
|
||||
|
||||
---@param x1 number
|
||||
---@param y1 number
|
||||
---@param x2 number
|
||||
---@param y2 number
|
||||
DrawLine = function(x1, y1, x2, y2)
|
||||
libhazel.RenderDrawLine(x1, y1, x2, y2)
|
||||
end,
|
||||
|
||||
---@param p1 Point
|
||||
---@param p2 Point
|
||||
DrawLineByPoints = function(p1, p2)
|
||||
libhazel.RenderDrawLine(p1.x, p1.y, p2.x, p2.y)
|
||||
end,
|
||||
|
||||
---@param x number
|
||||
---@param y number
|
||||
---@param w number
|
||||
---@param h number
|
||||
DrawRect = function(x, y, w, h)
|
||||
libhazel.RenderDrawRect(x, y, w, h)
|
||||
end,
|
||||
|
||||
---@param rect Rect
|
||||
DrawRectByRect = function(rect)
|
||||
libhazel.RenderDrawRect(rect.x, rect.y, rect.w, rect.h)
|
||||
end,
|
||||
|
||||
---@param x number
|
||||
---@param y number
|
||||
---@param w number
|
||||
---@param h number
|
||||
FillRect = function(x, y, w, h)
|
||||
libhazel.RenderFillRect(x, y, w, h)
|
||||
end,
|
||||
|
||||
---@param rect Rect
|
||||
FillRectByRect = function(rect)
|
||||
libhazel.RenderFillRect(rect.x, rect.y, rect.w, rect.h)
|
||||
end,
|
||||
|
||||
---@param texture Texture
|
||||
---@param srcrect Rect|nil
|
||||
---@param dstrect Rect|nil
|
||||
---@param flip number|nil
|
||||
DrawTexture = function(texture, srcrect, dstrect, flip)
|
||||
srcrect = srcrect or _M.CreateRect(0, 0, texture.w, texture.h)
|
||||
local size = _M.GetCanvaSize();
|
||||
dstrect = dstrect or _M.CreateRect(0, 0, size.x, size.y)
|
||||
libhazel.RenderDrawTexture(texture.rawPointer,
|
||||
srcrect.x, srcrect.y, srcrect.w, srcrect.h,
|
||||
dstrect.x, dstrect.y, dstrect.w, dstrect.h,
|
||||
flip or Flip.None)
|
||||
end,
|
||||
|
||||
Clear = function()
|
||||
libhazel.RenderClear()
|
||||
end
|
||||
}
|
||||
|
||||
_M.Renderer = Renderer
|
||||
|
||||
---@class Log
|
||||
local Log = {}
|
||||
|
||||
function Log.Loge(...)
|
||||
print("[Lua Error]:", ...)
|
||||
end
|
||||
|
||||
function Log.Logw(...)
|
||||
print("[Lua Warn]:", ...)
|
||||
end
|
||||
|
||||
function Log.Logi(...)
|
||||
print("[Lua Info]:", ...)
|
||||
end
|
||||
|
||||
_M.Log = Log
|
||||
|
||||
|
||||
---@class TextureStorage
|
||||
local TextureStorage = {
|
||||
storage = {}
|
||||
}
|
||||
|
||||
---@param filename string
|
||||
---@param name string
|
||||
---@return Texture
|
||||
function TextureStorage.LoadTexture(filename, name)
|
||||
local oldTexture = TextureStorage.storage[name]
|
||||
if oldTexture then
|
||||
_M.Log.Logw(string.format("%s already exists, delete it", name))
|
||||
_M.DestroyTexture(oldTexture)
|
||||
end
|
||||
local texture = _M.LoadTexture(filename)
|
||||
TextureStorage.storage[name] = texture
|
||||
return texture
|
||||
end
|
||||
|
||||
function TextureStorage.ClearAll()
|
||||
for _, v in pairs(TextureStorage.storage) do
|
||||
if v then
|
||||
_M.DestroyTexture(v)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---@return Texture
|
||||
---@param name string
|
||||
function TextureStorage.Get(name)
|
||||
return TextureStorage.storage[name]
|
||||
end
|
||||
|
||||
_M.TextureStorage = TextureStorage
|
||||
|
||||
---@class TileSheet
|
||||
---@field column number
|
||||
---@field row number
|
||||
---@field texture Texture
|
||||
---@field tileWidth number
|
||||
---@field tileHeight number
|
||||
local TileSheet = {}
|
||||
|
||||
---@return TileSheet
|
||||
---@param texture Texture
|
||||
---@param column number
|
||||
---@param row number
|
||||
function _M.CreateTileSheet(texture, column, row)
|
||||
local o = {texture = texture, column = column, row = row, tileWidth = texture.w / column, tileHeight = texture.h / row}
|
||||
setmetatable(o, {__index = TileSheet})
|
||||
return o
|
||||
end
|
||||
|
||||
---@param self TileSheet
|
||||
---@param column number
|
||||
---@param row number
|
||||
---@param dstrect Rect
|
||||
---@param flip number
|
||||
function TileSheet.Draw(self, column, row, dstrect, flip)
|
||||
local srcrect = _M.CreateRect(column * self.tileWidth, row * self.tileHeight, self.tileWidth, self.tileHeight)
|
||||
_M.Renderer.DrawTexture(self.texture, srcrect, dstrect, flip)
|
||||
end
|
||||
|
||||
_M.TileSheet = TileSheet
|
||||
|
||||
|
||||
local Time = { curTime = 0, elapseTime = 0 }
|
||||
|
||||
function Time.RecordElapseTime()
|
||||
local oldTime = Time.curTime
|
||||
Time.curTime = libhazel.GetTime()
|
||||
Time.elapseTime = Time.curTime - oldTime
|
||||
end
|
||||
|
||||
---@return number the passed seconds between two frames
|
||||
function Time.GetElapseTime()
|
||||
return Time.elapseTime
|
||||
end
|
||||
|
||||
_M.Time = Time
|
||||
|
||||
return _M
|
|
@ -0,0 +1,174 @@
|
|||
local hazel = require "hazel"
|
||||
local ECS = require "ecs"
|
||||
local constants = require "constants"
|
||||
local math = require "math"
|
||||
local content = require "content"
|
||||
local vmath = require "vmath"
|
||||
|
||||
local function drawCurosr()
|
||||
hazel.Renderer.SetDrawColor(1, 0, 0, 1)
|
||||
local pos = hazel.GetGameMousePos()
|
||||
local halfW = 10
|
||||
local halfH = 10
|
||||
hazel.Renderer.DrawRect(pos.x - halfW, pos.y - halfH, halfW * 2, halfH * 2)
|
||||
hazel.Renderer.DrawLine(pos.x - halfW + 5, pos.y, pos.x + halfW - 5, pos.y)
|
||||
hazel.Renderer.DrawLine(pos.x, pos.y - halfH + 5, pos.x, pos.y + halfH - 5)
|
||||
end
|
||||
|
||||
local FloorMap = {}
|
||||
|
||||
local function generateFloors()
|
||||
local xNum = math.ceil(hazel.GetCanvaSize().x / constants.TileSize)
|
||||
local yNum = math.ceil(hazel.GetCanvaSize().y / constants.TileSize)
|
||||
for x = 0, xNum do
|
||||
for y = 0, yNum do
|
||||
FloorMap[y + x * yNum] = math.random() <= constants.StonePutProbability
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function drawFloors()
|
||||
local xNum = math.ceil(hazel.GetCanvaSize().x / constants.TileSize)
|
||||
local yNum = math.ceil(hazel.GetCanvaSize().y / constants.TileSize)
|
||||
local tileIndex = {row = 9, col = 0}
|
||||
for x = 0, xNum do
|
||||
for y = 0, yNum do
|
||||
if FloorMap[y + x * yNum] then
|
||||
tileIndex.col = 1
|
||||
else
|
||||
tileIndex.col = 0
|
||||
end
|
||||
content.Tilesheet:Draw(tileIndex.col, tileIndex.row,
|
||||
hazel.CreateRect(x * constants.TileSize, y * constants.TileSize,
|
||||
constants.TileSize, constants.TileSize),
|
||||
hazel.Flip.None)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function updateBullet()
|
||||
for k, _ in pairs(content.BulletList) do
|
||||
---@type Entity
|
||||
local bullet = content.BulletList[k]
|
||||
bullet:Update()
|
||||
---@type Point
|
||||
local position = bullet:GetComponent(ECS.ComponentType.Transform).position
|
||||
if position.x + constants.TileSize <= 0 or
|
||||
position.x >= hazel.GetCanvaSize().x or
|
||||
position.y + constants.TileSize <= 0 or
|
||||
position.y >= hazel.GetCanvaSize().y then
|
||||
content.BulletList[k] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function updateMonster()
|
||||
---@param v Entity
|
||||
for _, v in pairs(content.MonsterList) do
|
||||
v:Update()
|
||||
end
|
||||
end
|
||||
|
||||
local function collisionDeal()
|
||||
---@type Rect
|
||||
local playerBox = content.PlayerEntity:GetComponent(ECS.ComponentType.ColliBox).rect
|
||||
---@type Point
|
||||
local playerPos = content.PlayerEntity:GetComponent(ECS.ComponentType.Transform).position
|
||||
---@type Rect
|
||||
local playerColliBox = hazel.CreateRect(playerPos.x + playerBox.x, playerPos.y + playerBox.y, playerBox.w, playerBox.h)
|
||||
---@type m Entity
|
||||
for km, _ in pairs(content.MonsterList) do
|
||||
---@type Entity
|
||||
local monster = content.MonsterList[km]
|
||||
---@type Point
|
||||
local monsterPos = monster:GetComponent(ECS.ComponentType.Transform).position
|
||||
---@type ColliBoxComponent
|
||||
local monsterBoxComponent = monster:GetComponent(ECS.ComponentType.ColliBox)
|
||||
if monsterBoxComponent then
|
||||
---@type Rect
|
||||
local monsterBox = monsterBoxComponent.rect
|
||||
---@type Rect
|
||||
local monsterColliBox = hazel.CreateRect(monsterPos.x + monsterBox.x, monsterPos.y + monsterBox.y,
|
||||
monsterBox.w, monsterBox.h)
|
||||
---@type RolePropComponent
|
||||
local monsterRoleProp = monster:GetComponent(ECS.ComponentType.RoleProp)
|
||||
if vmath.IsRectIntersect(playerColliBox, monsterColliBox) then
|
||||
---@type InvincibleComponent
|
||||
local playerInvincible = content.PlayerEntity:GetComponent(ECS.ComponentType.Invincible)
|
||||
if not playerInvincible:IsInvincibleState() then
|
||||
---@type RolePropComponent
|
||||
local playerRoleProp = content.PlayerEntity:GetComponent(ECS.ComponentType.RoleProp)
|
||||
playerRoleProp.hp = playerRoleProp.hp - monsterRoleProp.damage
|
||||
if playerRoleProp:IsDie() then
|
||||
content.PlayerEntity:RemoveComponent(ECS.ComponentType.Controller)
|
||||
content.PlayerEntity:RemoveComponent(ECS.ComponentType.Gun)
|
||||
content.PlayerEntity:RemoveComponent(ECS.ComponentType.Direction)
|
||||
content.PlayerEntity:RemoveComponent(ECS.ComponentType.HpShow)
|
||||
---@type ImageComponent
|
||||
local image = content.PlayerEntity:GetComponent(ECS.ComponentType.Image)
|
||||
image.row = 4
|
||||
image.col = 0
|
||||
else
|
||||
playerInvincible:IntoInvincible()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for kb, _ in pairs(content.BulletList) do
|
||||
---@type Entity
|
||||
local bullet = content.BulletList[kb]
|
||||
---@type Point
|
||||
local bulletPos = bullet:GetComponent(ECS.ComponentType.Transform).position
|
||||
---@type Rect
|
||||
local bulletBox = bullet:GetComponent(ECS.ComponentType.ColliBox).rect
|
||||
---@type Rect
|
||||
local bulletColliBox = hazel.CreateRect(bulletPos.x + bulletBox.x, bulletPos.y + bulletBox.y, bulletBox.w, bulletBox.h)
|
||||
if vmath.IsRectIntersect(bulletColliBox, monsterColliBox) then
|
||||
content.BulletList[kb] = nil
|
||||
local damage = bullet:GetComponent(ECS.ComponentType.Bullet).damage
|
||||
monsterRoleProp.hp = monsterRoleProp.hp - damage
|
||||
if monsterRoleProp:IsDie() then
|
||||
monster:RemoveComponent(ECS.ComponentType.Direction)
|
||||
monster:RemoveComponent(ECS.ComponentType.AI)
|
||||
monster:RemoveComponent(ECS.ComponentType.HpShow)
|
||||
monster:RemoveComponent(ECS.ComponentType.ColliBox)
|
||||
---@type ImageComponent
|
||||
local image = monster:GetComponent(ECS.ComponentType.Image)
|
||||
image.row = 4
|
||||
image.col = 2
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function GameStart()
|
||||
hazel.SetWindowIcon("resources/icon.png")
|
||||
content.Texture = hazel.LoadTexture("resources/tilesheet.png")
|
||||
content.Tilesheet = hazel.CreateTileSheet(content.Texture, 3, 10)
|
||||
content.PlayerEntity = ECS.CreatePlayer(hazel.CreatePos(constants.TileSize * 10, constants.TileSize * 10))
|
||||
table.insert(content.MonsterList, ECS.CreateMonster(hazel.CreatePos(500, 500)))
|
||||
|
||||
hazel.HideCursor()
|
||||
generateFloors()
|
||||
end
|
||||
|
||||
function GameLoop()
|
||||
hazel.Time.RecordElapseTime()
|
||||
|
||||
hazel.Renderer.SetClearColor(0, 0, 0, 1)
|
||||
hazel.Renderer.Clear()
|
||||
|
||||
drawFloors()
|
||||
updateMonster()
|
||||
content.PlayerEntity:Update()
|
||||
updateBullet()
|
||||
collisionDeal()
|
||||
drawCurosr()
|
||||
end
|
||||
|
||||
function GameQuit()
|
||||
hazel.ShowCursor()
|
||||
hazel.DestroyTexture(content.Texture)
|
||||
end
|
Binary file not shown.
After Width: | Height: | Size: 399 B |
Binary file not shown.
After Width: | Height: | Size: 5.4 KiB |
|
@ -0,0 +1,28 @@
|
|||
local math = require "math"
|
||||
local hazel = require "hazel"
|
||||
local _M = {}
|
||||
|
||||
---@return number
|
||||
---@param p Point
|
||||
function _M.Len(p)
|
||||
return math.sqrt(p.x * p.x + p.y * p.y)
|
||||
end
|
||||
|
||||
---@return Point
|
||||
---@param p
|
||||
function _M.Normalize(p)
|
||||
local l = _M.Len(p)
|
||||
return hazel.CreatePos(p.x / l, p.y / l)
|
||||
end
|
||||
|
||||
---@return boolean
|
||||
---@param r1 Rect
|
||||
---@param r2 Rect
|
||||
function _M.IsRectIntersect(r1, r2)
|
||||
return not (r1.x + r1.w < r2.x or
|
||||
r2.x + r2.w < r1.x or
|
||||
r2.y + r2.h < r1.y or
|
||||
r1.y + r1.h < r2.y)
|
||||
end
|
||||
|
||||
return _M
|
Reference in New Issue