project/build/default/main/player.scriptc
2025-08-25 01:59:20 +01:00

440 lines
No EOL
14 KiB
Text
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

šr
rlocal 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
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
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)
--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.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
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")
end
if message.group == hash("mummy") then
msg.post("main:/controller#main", "LevelCompleted")
--print("collision with mummy")
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")
--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
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
self.speed = 500
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@main/player.script"