project/main/player.script
2025-09-07 18:13:09 +01:00

514 lines
No EOL
17 KiB
Text

local Movement = {
STILL_LEFT = "STILL_LEFT",
STILL_RIGHT = "STILL_RIGHT",
MOVING_LEFT = "MOVING_LEFT",
MOVING_RIGHT = "MOVING_RIGHT",
CLIMBING_UP = "CLIMBING_UP",
CLIMBING_DOWN = "CLIMBING_DOWN",
FALLING = "FALLING",
JUMPING_LEFT = "JUMPING_LEFT",
JUMPING_RIGHT = "JUMPING_RIGHT",
JUMPING_STRAIGHT_UP = "JUMPING_STRAIGHT_UP",
CLIMBING_STILL = "CLIMBING_STILL",
}
local Actions = {
LEFT_ARROW_PRESS = "LEFT_ARROW_PRESS",
LEFT_ARROW_RELEASE = "LEFT_ARROW_RELEASE",
RIGHT_ARROW_PRESS = "RIGHT_ARROW_PRESS",
RIGHT_ARROW_RELEASE = "RIGHT_ARROW_RELEASE",
UP_ARROW_PRESS = "UP_ARROW_PRESS",
UP_ARROW_RELEASE = "UP_ARROW_RELEASE",
DOWN_ARROW_PRESS = "DOWN_ARROW_PRESS",
DOWN_ARROW_RELEASE = "DOWN_ARROW_RELEASE",
SPACE_BAR_PRESS = "SPACE_BAR_PRESS",
SPACE_BAR_RELEASE = "SPACE_BAR_RELEASE",
}
-- Transition table: [current_state][input] = next_state
local transitions = {
[Movement.STILL_RIGHT] = {
[Actions.RIGHT_ARROW_PRESS] = Movement.MOVING_RIGHT,
[Actions.RIGHT_ARROW_RELEASE] = Movement.STILL_RIGHT,
[Actions.LEFT_ARROW_PRESS] = Movement.MOVING_LEFT,
[Actions.LEFT_ARROW_RELEASE] = Movement.STILL_LEFT,
[Actions.UP_ARROW_PRESS] = Movement.CLIMBING_UP,
[Actions.UP_ARROW_RELEASE] = Movement.CLIMBING_STILL,
[Actions.DOWN_ARROW_PRESS] = Movement.CLIMBING_DOWN,
[Actions.DOWN_ARROW_RELEASE] = Movement.CLIMBING_STILL,
},
[Movement.STILL_LEFT] = {
[Actions.RIGHT_ARROW_PRESS] = Movement.MOVING_RIGHT,
[Actions.RIGHT_ARROW_RELEASE] = Movement.STILL_RIGHT,
[Actions.LEFT_ARROW_PRESS] = Movement.MOVING_LEFT,
[Actions.LEFT_ARROW_RELEASE] = Movement.STILL_LEFT,
[Actions.UP_ARROW_PRESS] = Movement.CLIMBING_UP,
[Actions.UP_ARROW_RELEASE] = Movement.CLIMBING_STILL,
[Actions.DOWN_ARROW_PRESS] = Movement.CLIMBING_DOWN,
[Actions.DOWN_ARROW_RELEASE] = Movement.CLIMBING_STILL,
},
[Movement.MOVING_LEFT] = {
[Actions.RIGHT_ARROW_PRESS] = Movement.MOVING_RIGHT,
[Actions.LEFT_ARROW_PRESS] = Movement.MOVING_LEFT,
[Actions.LEFT_ARROW_RELEASE] = Movement.STILL_LEFT,
[Actions.UP_ARROW_PRESS] = Movement.CLIMBING_UP,
[Actions.DOWN_ARROW_PRESS] = Movement.CLIMBING_DOWN,
},
[Movement.MOVING_RIGHT] = {
[Actions.RIGHT_ARROW_PRESS] = Movement.MOVING_RIGHT,
[Actions.RIGHT_ARROW_RELEASE] = Movement.STILL_RIGHT,
[Actions.LEFT_ARROW_PRESS] = Movement.MOVING_LEFT,
[Actions.UP_ARROW_PRESS] = Movement.CLIMBING_UP,
[Actions.DOWN_ARROW_PRESS] = Movement.CLIMBING_DOWN,
},
[Movement.CLIMBING_STILL] = {
[Actions.RIGHT_ARROW_PRESS] = Movement.MOVING_RIGHT,
[Actions.RIGHT_ARROW_RELEASE] = Movement.STILL_RIGHT,
[Actions.LEFT_ARROW_PRESS] = Movement.MOVING_LEFT,
[Actions.LEFT_ARROW_RELEASE] = Movement.STILL_LEFT,
[Actions.UP_ARROW_PRESS] = Movement.CLIMBING_UP,
[Actions.UP_ARROW_RELEASE] = Movement.CLIMBING_STILL,
[Actions.DOWN_ARROW_PRESS] = Movement.CLIMBING_DOWN,
[Actions.DOWN_ARROW_RELEASE] = Movement.CLIMBING_STILL,
},
[Movement.CLIMBING_UP] = {
[Actions.RIGHT_ARROW_PRESS] = Movement.MOVING_RIGHT,
[Actions.LEFT_ARROW_PRESS] = Movement.MOVING_LEFT,
[Actions.LEFT_ARROW_PRESS] = Movement.MOVING_LEFT,
[Actions.LEFT_ARROW_RELEASE] = Movement.STILL_LEFT,
[Actions.UP_ARROW_PRESS] = Movement.CLIMBING_UP,
[Actions.UP_ARROW_RELEASE] = Movement.CLIMBING_STILL,
[Actions.DOWN_ARROW_PRESS] = Movement.CLIMBING_DOWN,
[Actions.DOWN_ARROW_RELEASE] = Movement.CLIMBING_STILL,
},
[Movement.CLIMBING_DOWN] = {
[Actions.RIGHT_ARROW_PRESS] = Movement.MOVING_RIGHT,
[Actions.LEFT_ARROW_PRESS] = Movement.MOVING_LEFT,
[Actions.UP_ARROW_PRESS] = Movement.CLIMBING_UP,
[Actions.UP_ARROW_RELEASE] = Movement.CLIMBING_STILL,
[Actions.DOWN_ARROW_PRESS] = Movement.CLIMBING_DOWN,
[Actions.DOWN_ARROW_RELEASE] = Movement.CLIMBING_STILL,
},
}
function init(self)
msg.post(".", "acquire_input_focus")
self.direction = vmath.vector3(0,0,0)
self.speed = 250
self.gravity = -5000 -- gravity force
self.jump_velocity = 800-- how strong the jump is
self.velocity = vmath.vector3(0, 0, 0)
self.grounded = false
self.jumped = false
self.near_up_ladder = false
self.correction = vmath.vector3()
self.climbing = false
self.is_moving = 0
self.left_pressed = false
self.right_pressed = false
self.up_pressed = false
self.down_pressed = false
self.jump_pressed = false
self.have_amulet = false
self.amulet_timer = 0
self.regenerating = false
self.regen_timer = 0
self.blink_on_timer = 0
self.blink_off_timer = 0
self.paused = false
self.current_movement = Movement.STILL_RIGHT
self.current_level = "level1"
self.holding_key = false
self.scored = false
self.mummy_walking = false
self.touching_mummy = false
self.scored_jump = false
go.set_position(vmath.vector3(100,100,0.2))
end
function final(self)
-- Add finalization code here
-- Learn more: https://defold.com/manuals/script/
-- Remove this function if not needed
end
local function handleInput(self, input)
local Transitions = transitions[self.current_movement]
local next_movement = Transitions and Transitions[input]
if next_movement then
--print("Transitioning from", self.current_movement, "to", next_movement, "on input", input)
self.current_movement = next_movement
if next_movement == Movement.MOVING_LEFT then
sprite.play_flipbook("#sprite", hash("run_left"))
msg.post("holding_amulet", "left")
self.direction.x = -1
self.velocity.y = 0
end
if next_movement == Movement.MOVING_RIGHT then
sprite.play_flipbook("#sprite", hash("run_right"))
msg.post("holding_amulet", "right")
self.direction.x = 1
self.velocity.y = 0
end
if next_movement == Movement.STILL_RIGHT then
if not self.climbing then
sprite.play_flipbook("#sprite", hash("still_right"))
else
next_movement = Movement.CLIMBING_STILL
sprite.play_flipbook("#sprite", hash("still_climbing"))
end
self.direction.x = 0
end
if next_movement == Movement.STILL_LEFT then
if not self.climbing then
sprite.play_flipbook("#sprite", hash("still_left"))
else
next_movement = Movement.CLIMBING_STILL
sprite.play_flipbook("#sprite", hash("still_climbing"))
end
self.direction.x = 0
end
if next_movement == Movement.CLIMBING_STILL then
sprite.play_flipbook("#sprite", hash("still_climbing"))
self.velocity.y = 0
self.climbing = true
if self.right_pressed then
handleInput(self, Actions.RIGHT_ARROW_PRESS)
--print("Actions.LEFT_RIGHT_PRESS from climbing_still")
elseif self.left_pressed then
handleInput(self, Actions.LEFT_ARROW_PRESS)
--print("Actions.LEFT_ARROW_PRESS from climbing_still")
end
end
if next_movement == Movement.CLIMBING_UP then
sprite.play_flipbook("#sprite", hash("climbing"))
self.direction.x = 0
self.velocity.y = 150
self.climbing = true
end
if next_movement == Movement.CLIMBING_DOWN then
sprite.play_flipbook("#sprite", hash("climbing"))
self.direction.x = 0
self.velocity.y = -150
self.climbing = true
end
else
--print("No transition defined for", input, "in state", self.current_movement)
end
end
function update(self, dt)
if not self.paused then
if self.amulet_timer > 0 then
self.amulet_timer = self.amulet_timer - dt
-- print ("You have " .. self.amulet_timer .. " seconds left of amulet")
if self.amulet_timer < 0 then
self.amulet_timer = 0
self.have_amulet = false
msg.post("holding_amulet", "disable_sprite")
end
end
if self.regen_timer > 0 then
self.regen_timer = self.regen_timer - dt
-- print ("You have " .. self.regen_timer .. " seconds left of regeneration")
if self.regen_timer < 0 then
self.regen_timer = 0
self.regenerating = false
msg.post("#sprite", "enable")
end
if self.regenerating then
if self.blink_on_timer > 0 then
self.blink_on_timer = self.blink_on_timer - dt
msg.post("#sprite", "enable")
elseif self.blink_off_timer > 0 then
self.blink_off_timer = self.blink_off_timer - dt
msg.post("#sprite", "disable")
else
self.blink_on_timer = 0.25
self.blink_off_timer = 0.25
end
end
end
self.correction = vmath.vector3()
self.velocity.x = self.direction.x * self.speed
local pos = go.get_position()
pos = pos + self.velocity * dt
if pos.x < 24 then
pos.x = 24
elseif pos.x > 1030 then
pos.x = 1030
end
--if pos.y < 0 then
--pos.y = 100
--end
if pos.y < -20 then
pos.y = 100
pos.x = 100
msg.post("main:/controller#main", "LifeLost")
msg.post("main:/controller#main", "play dying sound")
self.current_movement = Movement.MOVING_RIGHT
handleInput(self, Actions.RIGHT_ARROW_RELEASE)
go.set_position(vmath.vector3(100,100,0.2))
self.regenerating = true
self.regen_timer = 3
end
local centre = vmath.vector3(pos.x, pos.y - 10, 0)
local platform = pos + vmath.vector3(0, -36, 0)
local ladder_up_left = pos + vmath.vector3(-24, -32, 0)
local ladder_up_right = pos + vmath.vector3(24, -32, 0)
local ladder_down_left = pos + vmath.vector3(-24, -42, 0)
local ladder_down_right = pos + vmath.vector3(24, -42, 0)
local curse = pos + vmath.vector3(0, -70, 0)
local feet = pos + vmath.vector3(0, -36, 0)
--msg.post("@render:", "draw_line", { start_point = centre, end_point = platform, color = vmath.vector4(1,0,0,1) })
--msg.post("@render:", "draw_line", { start_point = ladder_up_left, end_point = ladder_up_right, color = vmath.vector4(1,0,0,1) })
--msg.post("@render:", "draw_line", { start_point = ladder_up_right, end_point = ladder_up_left, color = vmath.vector4(1,0,0,1) })
--msg.post("@render:", "draw_line", { start_point = ladder_down_left, end_point = ladder_down_right, color = vmath.vector4(1,0,0,1) })
--msg.post("@render:", "draw_line", { start_point = ladder_down_right, end_point = ladder_down_left, color = vmath.vector4(1,0,0,1) })
local platform_result = physics.raycast(centre, platform, { hash("platform") })
if platform_result then
local point = platform_result.position - pos
-- msg.post("@render:", "draw_debug_text", { text = "Platform", position = vmath.vector3(20, 400, 0), color = vmath.vector4(1, 0, 0, 1) } )
-- msg.post("@render:", "draw_debug_text", { text = "X : " .. tostring(point.x), position = vmath.vector3(20, 380, 0), color = vmath.vector4(1, 0, 0, 1) } )
-- msg.post("@render:", "draw_debug_text", { text = "Y : " .. tostring(point.y), position = vmath.vector3(20, 360, 0), color = vmath.vector4(1, 0, 0, 1) } )
if not self.climbing then
self.jumped = false
self.speed = 250
self.grounded = true
self.scored_jump = false
self.velocity.y = 0
if point.y > -36 then
pos.y = pos.y + (point.y + 36)
end
--if self.climbing then
-- self.climbing = false
-- sprite.play_flipbook("#sprite", hash("still_left"))
--end
end
else
self.grounded = false
end
--testing points for jumping over curse
local curse_result = physics.raycast(feet, curse, { hash("curse") })
msg.post("@render:", "draw_line", { start_point = feet, end_point = curse, color = vmath.vector4(1,0,0,1) })
if curse_result and self.scored_jump == false then
msg.post("main:/controller#main", "add 10 points")
self.scored_jump = true
end
local ladder_up_result1 = physics.raycast(ladder_up_right, ladder_up_left, { hash("ladder") })
local ladder_up_result2 = physics.raycast(ladder_up_left, ladder_up_right, { hash("ladder") })
if ladder_up_result1 then
self.near_up_ladder = true
elseif ladder_up_result2 then
self.near_up_ladder = true
else
self.near_up_ladder = false
end
local ladder_down_result1 = physics.raycast(ladder_down_right, ladder_down_left, { hash("ladder") })
local ladder_down_result2 = physics.raycast(ladder_down_left, ladder_down_right, { hash("ladder") })
if ladder_down_result1 then
self.near_down_ladder = true
elseif ladder_down_result2 then
self.near_down_ladder = true
else
self.near_down_ladder = false
end
if not (self.near_up_ladder or self.near_down_ladder)then
if self.climbing then
self.climbing = false
if self.left_pressed then
handleInput(self, Actions.LEFT_ARROW_PRESS)
end
if self.right_pressed then
handleInput(self, Actions.RIGHT_ARROW_PRESS)
end
end
end
-- local debug_vars = {
-- x = pos.x,
-- y = pos.y,
-- x_vel = self.velocity.x,
-- y_vel = self.velocity.y,
-- grounded = self.grounded,
-- near_up_ladder = self.near_up_ladder,
-- near_down_ladder = self.near_down_ladder,
-- jumped = self.jumped,
-- climbing = self.climbing,
-- left_pressed = self.left_pressed,
-- right_pressed = self.right_pressed,
-- up_pressed = self.up_pressed,
-- down_pressed = self.down_pressed,
-- }
-- msg.post("#debug", "set_vars", debug_vars)
if not self.grounded and not ((self.near_up_ladder or self.near_down_ladder) and self.climbing) then
self.velocity.y = self.velocity.y + self.gravity * dt
end
go.set_position(pos)
end
end
function fixed_update(self, dt)
end
function on_message(self, message_id, message, sender)
if message_id == hash("contact_point_response") then
if message.group == hash("curse") then
if not self.regenerating then
--print("collision with curse")
msg.post(message.other_id, "dying")
end
end
if message.group == hash("amulet") then
self.have_amulet = true
self.amulet_timer = 5
msg.post("holding_amulet", "enable_sprite")
--print("collision with amulet")
msg.post("main:/controller#main", "play amulet sound")
end
if message.group == hash("mummy") then
-- sprite.play_flipbook("/mummy#still", "walking_mummy")
if self.touching_mummy == false then
self.mummy_walking = true
msg.post("mummy#mummy", "play_anim")
self.touching_mummy = true
end
if self.mummy_walking == false then
msg.post("main:/controller#main", "LevelCompleted")
msg.post("main:/controller#main", "play mummy sound")
end
--print("collision with mummy")
if self.current_level == "level3" then
msg.post("/mummy#mummy", "explode")
msg.post("mummy_explosion", "enable")
msg.post("main:/controller#main", "add 500 points")
print("500")
if self.holding_key == true then
msg.post("chest#sprite1", "enable")
msg.post("chest#sprite", "disable")
if self.scored == false then
msg.post("main:/controller#main", "add 1000 points")
print("1000")
self.scored = true
end
end
end
end
-- if message.group == hash("chest") then
-- if self.holding_key == true then
-- msg.post("chest#sprite1", "enable")
-- msg.post("chest#sprite", "disable")
-- msg.post("main:/controller#main", "add 1000 points")
-- end
-- end
if message.group == hash("key") then
self.holding_key = true
msg.post("level3:/key#sprite", "disable")
msg.post("key_symbol#sprite", "enable")
end
end
if message_id == hash("curse_dying_reply") then
if message.dying == false then
msg.post("/holding_amulet#holdingamulet", "disable_sprite")
msg.post("main:/controller#main", "LifeLost")
msg.post("main:/controller#main", "play dying sound")
--else
self.current_movement = Movement.MOVING_RIGHT
handleInput(self, Actions.RIGHT_ARROW_RELEASE)
go.set_position(vmath.vector3(100,100,0.2))
self.regenerating = true
self.regen_timer = 3
--end
end
end
if message_id == hash("pause") then
self.paused = true
end
if message_id == hash("unpause") then
self.paused = false
end
if message_id == hash("level1") then
self.current_level = "level1"
elseif message_id == hash("level2") then
self.current_level = "level2"
elseif message_id == hash("level3") then
self.current_level = "level3"
end
end
function on_input(self, action_id, action)
if not self.paused then
if action_id == hash("left") then
if action.pressed then
self.left_pressed = true
handleInput(self, Actions.LEFT_ARROW_PRESS)
elseif action.released then
self.left_pressed = false
handleInput(self, Actions.LEFT_ARROW_RELEASE)
end
end
if action_id == hash("right") then
if action.pressed then
self.right_pressed = true
handleInput(self, Actions.RIGHT_ARROW_PRESS)
elseif action.released then
self.right_pressed = false
handleInput(self, Actions.RIGHT_ARROW_RELEASE)
end
end
if action_id == hash("jump") and action.pressed and not self.jumped and not self.climbing then
self.velocity.y = self.jump_velocity
msg.post("main:/controller#main", "play jump sound")
if self.current_level == "level2" or self.current_level == "level3" then
self.speed = 500
end
self.jumped = true
end
if action_id == hash("climb_up") then
if action.pressed then
self.up_pressed = true
handleInput(self, Actions.UP_ARROW_PRESS)
elseif action.released then
self.up_pressed = false
handleInput(self, Actions.UP_ARROW_RELEASE)
end
end
if action_id == hash("climb_down") then
if action.pressed then
self.down_pressed = true
handleInput(self, Actions.DOWN_ARROW_PRESS)
elseif action.released then
self.down_pressed = false
handleInput(self, Actions.DOWN_ARROW_RELEASE)
end
end
end
end
function on_reload(self)
-- Add reload-handling code here
-- Learn more: https://defold.com/manuals/hot-reload/
-- Remove this function if not needed
end