Add new maps and tileset for the game world
- Created room1.tmx and room1.lua for the first room in the game, including tiles, collision objects, and NPCs. - Added room2.tmx and room2.lua for the second room, featuring tiles, collision objects, and an enemy. - Introduced a world template to manage map transitions and layout. - Implemented a new tileset (castle.tsx and castle.lua) for the castle theme, including tile properties and image references.
This commit is contained in:
30
scripts/battle/bullets/arenahazard.lua
Normal file
30
scripts/battle/bullets/arenahazard.lua
Normal file
@@ -0,0 +1,30 @@
|
||||
---@class ArenaHazard : Bullet
|
||||
local ArenaHazard, super = Class(Bullet)
|
||||
|
||||
---@param x number # The X position of the bullet
|
||||
---@param y number # The Y position of the bullet
|
||||
---@param rot number # The rotation (in radians) of the bullet
|
||||
function ArenaHazard:init(x, y, rot)
|
||||
-- Last argument = sprite path
|
||||
super.init(self, x, y, "bullets/arenahazard")
|
||||
|
||||
-- Top-center origin point (will be rotated around it)
|
||||
self:setOrigin(0.5, 0)
|
||||
|
||||
-- The hitbox where the player will be damaged by the bullet (affected by scale and rotation)
|
||||
self:setHitbox(0, 0, self.width, 8)
|
||||
|
||||
-- Rotation of the bullet (in radians)
|
||||
self.rotation = rot
|
||||
|
||||
-- Don't destroy this bullet when it damages the player
|
||||
self.destroy_on_hit = false
|
||||
end
|
||||
|
||||
function ArenaHazard:update()
|
||||
-- For more complicated bullet behaviours, code here gets called every update
|
||||
|
||||
super.update(self)
|
||||
end
|
||||
|
||||
return ArenaHazard
|
||||
24
scripts/battle/bullets/smallbullet.lua
Normal file
24
scripts/battle/bullets/smallbullet.lua
Normal file
@@ -0,0 +1,24 @@
|
||||
---@class SmallBullet : Bullet
|
||||
local SmallBullet, super = Class(Bullet)
|
||||
|
||||
---@param x number # The X position of the bullet
|
||||
---@param y number # The Y position of the bullet
|
||||
---@param dir number # The dir (in radians) of the bullet
|
||||
---@param speed number # The speed the bullet will move at in the specified direction
|
||||
function SmallBullet:init(x, y, dir, speed)
|
||||
-- Last argument = sprite path
|
||||
super.init(self, x, y, "bullets/smallbullet")
|
||||
|
||||
-- Move the bullet in dir radians (0 = right, pi = left, clockwise rotation)
|
||||
self.physics.direction = dir
|
||||
-- Speed the bullet moves (pixels per frame at 30FPS)
|
||||
self.physics.speed = speed
|
||||
end
|
||||
|
||||
function SmallBullet:update()
|
||||
-- For more complicated bullet behaviours, code here gets called every update
|
||||
|
||||
super.update(self)
|
||||
end
|
||||
|
||||
return SmallBullet
|
||||
24
scripts/battle/cutscenes/dummy.lua
Normal file
24
scripts/battle/cutscenes/dummy.lua
Normal file
@@ -0,0 +1,24 @@
|
||||
return {
|
||||
-- The inclusion of the below line tells the language server that the first parameter of the cutscene is `BattleCutscene`.
|
||||
-- This allows it to fetch us useful documentation that shows all of the available cutscene functions while writing our cutscenes!
|
||||
|
||||
---@param cutscene BattleCutscene
|
||||
susie_punch = function(cutscene, battler, enemy)
|
||||
-- Open textbox and wait for completion
|
||||
cutscene:text("* Susie threw a punch at\nthe dummy.")
|
||||
|
||||
-- Hurt the target enemy for 1 damage
|
||||
Assets.playSound("damage")
|
||||
enemy:hurt(1, battler)
|
||||
-- Wait 1 second
|
||||
cutscene:wait(1)
|
||||
|
||||
-- Susie text
|
||||
cutscene:text("* You,[wait:5] uh,[wait:5] look like a weenie.[wait:5]\n* I don't like beating up\npeople like that.", "nervous_side", "susie")
|
||||
|
||||
if cutscene:getCharacter("ralsei") then
|
||||
-- Ralsei text, if he's in the party
|
||||
cutscene:text("* Aww,[wait:5] Susie!", "blush_pleased", "ralsei")
|
||||
end
|
||||
end
|
||||
}
|
||||
21
scripts/battle/encounters/dummy.lua
Normal file
21
scripts/battle/encounters/dummy.lua
Normal file
@@ -0,0 +1,21 @@
|
||||
local Dummy, super = Class(Encounter)
|
||||
|
||||
function Dummy:init()
|
||||
super.init(self)
|
||||
|
||||
-- Text displayed at the bottom of the screen at the start of the encounter
|
||||
self.text = "* The tutorial begins...?"
|
||||
|
||||
-- Battle music ("battle" is rude buster)
|
||||
self.music = "battle"
|
||||
-- Enables the purple grid battle background
|
||||
self.background = true
|
||||
|
||||
-- Add the dummy enemy to the encounter
|
||||
self:addEnemy("dummy")
|
||||
|
||||
--- Uncomment this line to add another!
|
||||
--self:addEnemy("dummy")
|
||||
end
|
||||
|
||||
return Dummy
|
||||
96
scripts/battle/enemies/dummy.lua
Normal file
96
scripts/battle/enemies/dummy.lua
Normal file
@@ -0,0 +1,96 @@
|
||||
local Dummy, super = Class(EnemyBattler)
|
||||
|
||||
function Dummy:init()
|
||||
super.init(self)
|
||||
|
||||
-- Enemy name
|
||||
self.name = "Dummy"
|
||||
-- Sets the actor, which handles the enemy's sprites (see scripts/data/actors/dummy.lua)
|
||||
self:setActor("dummy")
|
||||
|
||||
-- Enemy health
|
||||
self.max_health = 450
|
||||
self.health = 450
|
||||
-- Enemy attack (determines bullet damage)
|
||||
self.attack = 4
|
||||
-- Enemy defense (usually 0)
|
||||
self.defense = 0
|
||||
-- Enemy reward
|
||||
self.money = 100
|
||||
|
||||
-- Mercy given when sparing this enemy before its spareable (20% for basic enemies)
|
||||
self.spare_points = 20
|
||||
|
||||
-- List of possible wave ids, randomly picked each turn
|
||||
self.waves = {
|
||||
"basic",
|
||||
"aiming",
|
||||
"movingarena"
|
||||
}
|
||||
|
||||
-- Dialogue randomly displayed in the enemy's speech bubble
|
||||
self.dialogue = {
|
||||
"..."
|
||||
}
|
||||
|
||||
-- Check text (automatically has "ENEMY NAME - " at the start)
|
||||
self.check = "AT 4 DF 0\n* Cotton heart and button eye\n* Looks just like a fluffy guy."
|
||||
|
||||
-- Text randomly displayed at the bottom of the screen each turn
|
||||
self.text = {
|
||||
"* The dummy gives you a soft\nsmile.",
|
||||
"* The power of fluffy boys is\nin the air.",
|
||||
"* Smells like cardboard.",
|
||||
}
|
||||
-- Text displayed at the bottom of the screen when the enemy has low health
|
||||
self.low_health_text = "* The dummy looks like it's\nabout to fall over."
|
||||
|
||||
-- Register act called "Smile"
|
||||
self:registerAct("Smile")
|
||||
-- Register party act with Ralsei called "Tell Story"
|
||||
-- (second argument is description, usually empty)
|
||||
self:registerAct("Tell Story", "", {"ralsei"})
|
||||
end
|
||||
|
||||
function Dummy:onAct(battler, name)
|
||||
if name == "Smile" then
|
||||
-- Give the enemy 100% mercy
|
||||
self:addMercy(100)
|
||||
-- Change this enemy's dialogue for 1 turn
|
||||
self.dialogue_override = "... ^^"
|
||||
-- Act text (since it's a list, multiple textboxes)
|
||||
return {
|
||||
"* You smile.[wait:5]\n* The dummy smiles back.",
|
||||
"* It seems the dummy just wanted\nto see you happy."
|
||||
}
|
||||
|
||||
elseif name == "Tell Story" then
|
||||
-- Loop through all enemies
|
||||
for _, enemy in ipairs(Game.battle.enemies) do
|
||||
-- Make the enemy tired
|
||||
enemy:setTired(true)
|
||||
end
|
||||
return "* You and Ralsei told the dummy\na bedtime story.\n* The enemies became [color:blue]TIRED[color:reset]..."
|
||||
|
||||
elseif name == "Standard" then --X-Action
|
||||
-- Give the enemy 50% mercy
|
||||
self:addMercy(50)
|
||||
if battler.chara.id == "ralsei" then
|
||||
-- R-Action text
|
||||
return "* Ralsei bowed politely.\n* The dummy spiritually bowed\nin return."
|
||||
elseif battler.chara.id == "susie" then
|
||||
-- S-Action: start a cutscene (see scripts/battle/cutscenes/dummy.lua)
|
||||
Game.battle:startActCutscene("dummy", "susie_punch")
|
||||
return
|
||||
else
|
||||
-- Text for any other character (like Noelle)
|
||||
return "* "..battler.chara:getName().." straightened the\ndummy's hat."
|
||||
end
|
||||
end
|
||||
|
||||
-- If the act is none of the above, run the base onAct function
|
||||
-- (this handles the Check act)
|
||||
return super.onAct(self, battler, name)
|
||||
end
|
||||
|
||||
return Dummy
|
||||
30
scripts/battle/waves/aiming.lua
Normal file
30
scripts/battle/waves/aiming.lua
Normal file
@@ -0,0 +1,30 @@
|
||||
local Aiming, super = Class(Wave)
|
||||
|
||||
function Aiming:onStart()
|
||||
-- Every 0.5 seconds...
|
||||
self.timer:every(1 / 2, function()
|
||||
-- Get all enemies that selected this wave as their attack
|
||||
local attackers = self:getAttackers()
|
||||
|
||||
-- Loop through all attackers
|
||||
for _, attacker in ipairs(attackers) do
|
||||
|
||||
-- Get the attacker's center position
|
||||
local x, y = attacker:getRelativePos(attacker.width / 2, attacker.height / 2)
|
||||
|
||||
-- Get the angle between the bullet position and the soul's position
|
||||
local angle = MathUtils.angle(x, y, Game.battle.soul.x, Game.battle.soul.y)
|
||||
|
||||
-- Spawn smallbullet angled towards the player with speed 8 (see scripts/battle/bullets/smallbullet.lua)
|
||||
self:spawnBullet("smallbullet", x, y, angle, 8)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function Aiming:update()
|
||||
-- Code here gets called every frame
|
||||
|
||||
super.update(self)
|
||||
end
|
||||
|
||||
return Aiming
|
||||
25
scripts/battle/waves/basic.lua
Normal file
25
scripts/battle/waves/basic.lua
Normal file
@@ -0,0 +1,25 @@
|
||||
local Basic, super = Class(Wave)
|
||||
|
||||
function Basic:onStart()
|
||||
-- Every 0.33 seconds...
|
||||
self.timer:every(1 / 3, function()
|
||||
-- Our X position is offscreen, to the right
|
||||
local x = SCREEN_WIDTH + 20
|
||||
-- Get a random Y position between the top and the bottom of the arena
|
||||
local y = MathUtils.random(Game.battle.arena.top, Game.battle.arena.bottom)
|
||||
|
||||
-- Spawn smallbullet going left with speed 8 (see scripts/battle/bullets/smallbullet.lua)
|
||||
local bullet = self:spawnBullet("smallbullet", x, y, math.rad(180), 8)
|
||||
|
||||
-- Dont remove the bullet offscreen, because we spawn it offscreen
|
||||
bullet.remove_offscreen = false
|
||||
end)
|
||||
end
|
||||
|
||||
function Basic:update()
|
||||
-- Code here gets called every frame
|
||||
|
||||
super.update(self)
|
||||
end
|
||||
|
||||
return Basic
|
||||
38
scripts/battle/waves/movingarena.lua
Normal file
38
scripts/battle/waves/movingarena.lua
Normal file
@@ -0,0 +1,38 @@
|
||||
local MovingArena, super = Class(Wave)
|
||||
|
||||
function MovingArena:init()
|
||||
super.init(self)
|
||||
|
||||
-- Initialize timer
|
||||
self.siner = 0
|
||||
end
|
||||
|
||||
function MovingArena:onStart()
|
||||
-- Get the arena object
|
||||
local arena = Game.battle.arena
|
||||
|
||||
-- Spawn spikes on top of arena
|
||||
self:spawnBulletTo(Game.battle.arena, "arenahazard", arena.width / 2, 0, math.rad(0))
|
||||
|
||||
-- Spawn spikes on bottom of arena (rotated 180 degrees)
|
||||
self:spawnBulletTo(Game.battle.arena, "arenahazard", arena.width / 2, arena.height, math.rad(180))
|
||||
|
||||
-- Store starting arena position
|
||||
self.arena_start_x = arena.x
|
||||
self.arena_start_y = arena.y
|
||||
end
|
||||
|
||||
function MovingArena:update()
|
||||
-- Increment timer for arena movement
|
||||
self.siner = self.siner + DT
|
||||
|
||||
-- Calculate the arena Y offset
|
||||
local offset = math.sin(self.siner * 1.5) * 60
|
||||
|
||||
-- Move the arena
|
||||
Game.battle.arena:setPosition(self.arena_start_x, self.arena_start_y + offset)
|
||||
|
||||
super.update(self)
|
||||
end
|
||||
|
||||
return MovingArena
|
||||
Reference in New Issue
Block a user