add start logo; player now flash when hurted
This commit is contained in:
parent
5504ce68d2
commit
a86f0719fb
|
@ -0,0 +1,14 @@
|
|||
[important]
|
||||
[x] 加上1MGames标志
|
||||
|
||||
[ ] 角色走路动画
|
||||
[ ] 角色受伤特效
|
||||
[x] 角色无敌时闪烁
|
||||
[ ] 新增多个枪类型
|
||||
[ ] 右上角显示分数
|
||||
[ ] 玩家积分榜
|
||||
|
||||
[optional]
|
||||
[ ] 怪物从土里爬出来(新增怪物类型)
|
||||
[ ] 掉落宝物(掉落子弹,加分道具)
|
||||
[ ] 多把武器切换
|
|
@ -1,5 +1,7 @@
|
|||
local _M = {}
|
||||
|
||||
_M.ShowLicenseTime = 2.5
|
||||
|
||||
_M.TileSize = 32
|
||||
_M.PlayerInfo = {
|
||||
velocity = 250,
|
||||
|
|
|
@ -10,8 +10,8 @@ _M.RestartHintTexture = nil
|
|||
---@type Texture
|
||||
_M.StartHintTexture = nil
|
||||
|
||||
---@type boolean
|
||||
_M.IsStartGame = false
|
||||
---@type Texture
|
||||
_M.LicensTexture = nil
|
||||
|
||||
---@type TileSheet
|
||||
_M.Tilesheet = nil
|
||||
|
@ -22,6 +22,14 @@ _M.PlayerEntity = nil
|
|||
---@type table<Entity>
|
||||
_M.BulletList = {}
|
||||
|
||||
_M.GameStateEnum = {
|
||||
ShowLogo = 1,
|
||||
WaitStart = 2,
|
||||
Gaming = 3,
|
||||
}
|
||||
|
||||
_M.GameState = _M.GameStateEnum.ShowLogo
|
||||
|
||||
---@type table<Entity>
|
||||
_M.MonsterList = {}
|
||||
|
||||
|
|
106
game/ecs.lua
106
game/ecs.lua
|
@ -3,6 +3,7 @@ local constants = require "constants"
|
|||
local math = require "math"
|
||||
local vmath = require "vmath"
|
||||
local content = require "content"
|
||||
local timer = require "timer"
|
||||
|
||||
---@class ECS
|
||||
local _M = {}
|
||||
|
@ -203,7 +204,6 @@ end
|
|||
---@class ControllerComponent:Component
|
||||
|
||||
---@return ControllerComponent
|
||||
---@param speed number
|
||||
function _M.CreateControllerComponent()
|
||||
local o = { isActive = true, name = ComponentType.Controller, parent = nil }
|
||||
|
||||
|
@ -229,6 +229,12 @@ function _M.CreateControllerComponent()
|
|||
transform.position.y = transform.position.y + speed * elapseTime
|
||||
end
|
||||
|
||||
local canvaSize = hazel.GetCanvaSize()
|
||||
if transform.position.x < 0 then transform.position.x = 0 end
|
||||
if transform.position.x + transform.size.x > canvaSize.x then transform.position.x = canvaSize.x - transform.size.x end
|
||||
if transform.position.y < constants.PlayerHpBarInfo.height then transform.position.y = constants.PlayerHpBarInfo.height end
|
||||
if transform.position.y + transform.size.y > canvaSize.y then transform.position.y = canvaSize.y - transform.size.y end
|
||||
|
||||
---@type Point
|
||||
local mousePos = hazel.GetGameMousePos()
|
||||
|
||||
|
@ -239,6 +245,14 @@ function _M.CreateControllerComponent()
|
|||
---@type Point
|
||||
local mouseDir = hazel.CreatePos(mousePos.x - playerCenterX, mousePos.y - playerCenterY)
|
||||
self:GetParent():GetComponent(ComponentType.Direction):SetDir(mouseDir)
|
||||
|
||||
if hazel.GetMouseButtonState(hazel.MouseButton.Left) == hazel.InputState.Press then
|
||||
---@type GunComponent
|
||||
local gun = self:GetParent():GetComponent(ComponentType.Gun)
|
||||
if gun then
|
||||
gun:Fire(vmath.Normalize(mouseDir))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return _M.CreateComponent(o)
|
||||
|
@ -250,26 +264,54 @@ end
|
|||
---@return InvincibleComponent
|
||||
---@param time number
|
||||
function _M.CreateInvincibleComponent(time)
|
||||
local o = { isActive = true, name = ComponentType.Invincible, cooldown = time, timeCountDown = time, parent = nil }
|
||||
local o = { isActive = true, name = ComponentType.Invincible, isInvincible = false, parent = nil }
|
||||
o.flashTimer = nil
|
||||
---@type Timer
|
||||
o.cdTimer = timer.CreateTimer(time, 1, function ()
|
||||
o.isInvincible = false
|
||||
end)
|
||||
o.cdTimer:Stop()
|
||||
|
||||
---@return boolean
|
||||
---@param self InvincibleComponent
|
||||
o.IsInvincibleState = function(self)
|
||||
return self.timeCountDown > 0
|
||||
return self.cdTimer:IsRunning()
|
||||
end
|
||||
|
||||
---@param self InvincibleComponent
|
||||
o.IntoInvincible = function(self)
|
||||
if self.timeCountDown <= 0 then
|
||||
self.timeCountDown = self.cooldown
|
||||
if self.isInvincible then
|
||||
return
|
||||
end
|
||||
self.isInvincible = true
|
||||
self.cdTimer:Rewind()
|
||||
self.cdTimer:Start()
|
||||
self.flashTimer = timer.CreateTimer(0.1, time / 0.1,
|
||||
function()
|
||||
---@type ImageComponent
|
||||
local image = o:GetParent():GetComponent(ComponentType.Image)
|
||||
if image then
|
||||
if image:IsActive() then
|
||||
image:Disable()
|
||||
else
|
||||
image:Enable()
|
||||
end
|
||||
end
|
||||
end,
|
||||
function()
|
||||
---@type ImageComponent
|
||||
local image = o:GetParent():GetComponent(ComponentType.Image)
|
||||
if image then
|
||||
image:Enable()
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
---@param self InvincibleComponent
|
||||
o.Update = function(self)
|
||||
self.timeCountDown = self.timeCountDown - hazel.Time.GetElapseTime()
|
||||
if self.timeCountDown < 0 then
|
||||
self.timeCountDown = 0
|
||||
self.cdTimer:Update()
|
||||
if self.flashTimer then
|
||||
self.flashTimer:Update()
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -368,34 +410,39 @@ end
|
|||
---@param damage number
|
||||
---@param velocity number
|
||||
function _M.CreateGunComponent(damage, velocity)
|
||||
local o = { isActive = true, name = ComponentType.Gun, damage = damage, timeCounter = 0, parent = nil }
|
||||
local o = { isActive = true, name = ComponentType.Gun, damage = damage, canShoot = true, velocity = velocity, parent = nil }
|
||||
o.cdTimer = timer.CreateTimer(constants.GunInfo.cooldown, -1, function()
|
||||
o.canShoot = true
|
||||
end)
|
||||
|
||||
---@param self GunComponent
|
||||
---@param dir Point
|
||||
o.Fire = function(self, dir)
|
||||
if not self.canShoot then
|
||||
return
|
||||
end
|
||||
---@type Point
|
||||
local position = self:GetParent():GetComponent(ComponentType.Transform).position
|
||||
local playerCenterX = position.x + constants.TileSize / 2
|
||||
local playerCenterY = position.y + constants.TileSize / 2
|
||||
local ndir = vmath.Normalize(dir)
|
||||
local bullet = _M.CreateBullet(hazel.CreatePos(playerCenterX - constants.TileSize / 2, playerCenterY - constants.TileSize / 2),
|
||||
self.damage,
|
||||
hazel.CreatePos(ndir.x * self.velocity, ndir.y * self.velocity))
|
||||
table.insert(content.BulletList, bullet)
|
||||
|
||||
self.canShoot = false
|
||||
end
|
||||
|
||||
---@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
|
||||
self.cdTimer:Update()
|
||||
end
|
||||
|
||||
return _M.CreateComponent(o)
|
||||
end
|
||||
|
||||
|
||||
|
||||
---@class BulletComponent:Component
|
||||
---@field damage number
|
||||
---@field speed Point
|
||||
|
@ -449,6 +496,7 @@ function _M.CreatePlayer(pos)
|
|||
entity:SetComponent(_M.CreateImageComponent(content.Tilesheet, 0, 0))
|
||||
entity:SetComponent(_M.CreateRolePropComponent(constants.PlayerInfo.hp, constants.PlayerInfo.velocity))
|
||||
entity:SetComponent(_M.CreateDirectionComponent(0))
|
||||
entity:SetComponent(_M.CreateGunComponent(constants.BulletInfo.damage, constants.BulletInfo.velocity))
|
||||
entity:SetComponent(_M.CreateColliBoxComponent(constants.RoleColliBox))
|
||||
entity:SetComponent(_M.CreateInvincibleComponent(constants.Invincible))
|
||||
return entity
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
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 timer = require "timer"
|
||||
|
||||
local function drawCurosr()
|
||||
hazel.Renderer.SetDrawColor(1, 0, 0, 1)
|
||||
|
@ -170,7 +170,7 @@ local function initGame()
|
|||
content.MonsterList = {}
|
||||
content.PlayerEntity = ECS.CreatePlayer(hazel.CreatePos(constants.TileSize * 16, constants.TileSize * 13))
|
||||
content.MonsterBirthNum = constants.MonsterBirthInitNum
|
||||
content.IsStartGame = false
|
||||
content.GameState = content.GameStateEnum.WaitStart
|
||||
end
|
||||
|
||||
local function generateMonster()
|
||||
|
@ -205,15 +205,26 @@ local function generateMonster()
|
|||
content.MonsterBirthCountDown = constants.MonsterBirthInterval
|
||||
end
|
||||
|
||||
---@type Timer
|
||||
local showLicenseTimer = nil
|
||||
|
||||
function GameStart()
|
||||
hazel.SetWindowIcon("resources/icon.png")
|
||||
content.Texture = hazel.LoadTexture("resources/tilesheet.png")
|
||||
content.RestartHintTexture = hazel.LoadTexture("resources/RestartHint.png")
|
||||
content.LicensTexture = hazel.LoadTexture("resources/License.png")
|
||||
content.StartHintTexture = hazel.LoadTexture("resources/StartHint.png")
|
||||
content.Tilesheet = hazel.CreateTileSheet(content.Texture, 3, 10)
|
||||
|
||||
initGame()
|
||||
|
||||
content.GameState = content.GameStateEnum.ShowLogo
|
||||
|
||||
showLicenseTimer = timer.CreateTimer(constants.ShowLicenseTime, 1, function()
|
||||
content.GameState = content.GameStateEnum.WaitStart
|
||||
showLicenseTimer = nil
|
||||
end)
|
||||
|
||||
hazel.HideCursor()
|
||||
generateFloors()
|
||||
end
|
||||
|
@ -221,14 +232,21 @@ end
|
|||
function GameLoop()
|
||||
hazel.Time.RecordElapseTime()
|
||||
|
||||
if showLicenseTimer then
|
||||
showLicenseTimer:Update()
|
||||
end
|
||||
|
||||
hazel.Renderer.SetClearColor(0, 0, 0, 1)
|
||||
hazel.Renderer.Clear()
|
||||
|
||||
drawFloors()
|
||||
updateMonster()
|
||||
content.PlayerEntity:Update()
|
||||
updateBullet()
|
||||
collisionDeal()
|
||||
if content.GameState == content.GameStateEnum.ShowLogo then
|
||||
local dstrect = hazel.CreateRect(0, 0, 0, 0)
|
||||
dstrect.w = content.LicensTexture.w * 5
|
||||
dstrect.h = content.LicensTexture.h * 5
|
||||
dstrect.x = (hazel.GetCanvaSize().x - dstrect.w) / 2
|
||||
dstrect.y = (hazel.GetCanvaSize().y - dstrect.h) / 2
|
||||
hazel.Renderer.DrawTexture(content.LicensTexture, nil, dstrect)
|
||||
end
|
||||
|
||||
---@type RolePropComponent
|
||||
local playerRoleInfo = content.PlayerEntity:GetComponent(ECS.ComponentType.RoleProp)
|
||||
|
@ -239,12 +257,20 @@ function GameLoop()
|
|||
end
|
||||
end
|
||||
|
||||
if not content.IsStartGame then
|
||||
if content.GameState == content.GameStateEnum.WaitStart or content.GameState == content.GameStateEnum.Gaming then
|
||||
drawFloors()
|
||||
updateMonster()
|
||||
content.PlayerEntity:Update()
|
||||
updateBullet()
|
||||
collisionDeal()
|
||||
drawCurosr()
|
||||
end
|
||||
|
||||
if content.GameState == content.GameStateEnum.WaitStart then
|
||||
showStartHint()
|
||||
if hazel.GetMouseButtonState(hazel.MouseButton.Left) == hazel.InputState.Press then
|
||||
content.IsStartGame = true
|
||||
content.GameState = content.GameStateEnum.Gaming
|
||||
content.PlayerEntity:SetComponent(ECS.CreateControllerComponent())
|
||||
content.PlayerEntity:SetComponent(ECS.CreateGunComponent(constants.BulletInfo.damage, constants.BulletInfo.velocity))
|
||||
content.PlayerEntity:SetComponent(ECS.CreateHpShowComponent(hazel.CreateSize(constants.PlayerHpBarInfo.width, constants.PlayerHpBarInfo.height)))
|
||||
|
||||
for _, v in pairs(content.MonsterList) do
|
||||
|
@ -253,13 +279,11 @@ function GameLoop()
|
|||
end
|
||||
end
|
||||
|
||||
if content.IsStartGame then
|
||||
if content.GameState == content.GameStateEnum.Gaming then
|
||||
for i = 0, content.MonsterBirthNum do
|
||||
generateMonster()
|
||||
end
|
||||
end
|
||||
|
||||
drawCurosr()
|
||||
end
|
||||
|
||||
function GameQuit()
|
||||
|
@ -267,4 +291,5 @@ function GameQuit()
|
|||
hazel.DestroyTexture(content.Texture)
|
||||
hazel.DestroyTexture(content.RestartHintTexture)
|
||||
hazel.DestroyTexture(content.StartHintTexture)
|
||||
hazel.DestroyTexture(content.LicensTexture)
|
||||
end
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 831 B |
|
@ -0,0 +1,59 @@
|
|||
local hazel = require "hazel"
|
||||
|
||||
---@class Timer
|
||||
local _M = {}
|
||||
|
||||
---@param interval number seconds
|
||||
---@param loop number -1 means infinite loop
|
||||
---@param callback function|nil a no param, no return value callback function
|
||||
---@param onStopFunc function|nil a no param, no return value callback function called when timer stop
|
||||
function _M.CreateTimer(interval, loop, callback, onStopFunc)
|
||||
local o = {isStart = true, interval = interval, totleLoop = loop, loop = loop, callback = callback, onStopFunc = onStopFunc, counter = 0}
|
||||
setmetatable(o, {__index = _M})
|
||||
return o
|
||||
end
|
||||
|
||||
---@param self Timer
|
||||
function _M.Rewind(self)
|
||||
self.loop = self.totleLoop
|
||||
end
|
||||
|
||||
---@param self Timer
|
||||
function _M.Start(self)
|
||||
self.isStart = true
|
||||
end
|
||||
|
||||
---@return boolean
|
||||
---@param self Timer
|
||||
function _M.IsRunning(self)
|
||||
return self.isStart
|
||||
end
|
||||
|
||||
---@param self Timer
|
||||
function _M.Stop(self)
|
||||
self.isStart = false
|
||||
end
|
||||
|
||||
---@param self Timer
|
||||
function _M.Update(self)
|
||||
if self.loop == 0 then
|
||||
if self:IsRunning() then
|
||||
if self.onStopFunc then
|
||||
self.onStopFunc()
|
||||
end
|
||||
self:Stop()
|
||||
end
|
||||
end
|
||||
if self:IsRunning() then
|
||||
self.counter = self.counter + hazel.Time.GetElapseTime()
|
||||
while self.counter >= self.interval do
|
||||
self.counter = self.counter - self.interval
|
||||
self.loop = self.loop - 1
|
||||
if self.callback then
|
||||
self.callback()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return _M
|
Reference in New Issue