Arikase
Arikase

Reputation: 1

lua solar2d. player passes through obstacles and incorrect transition to another level

lua solar2d. I have a player and obstacles, I grouped the hitbox and texture to move together, but then the event of collision between the player and the obstacle is not processed, without the group and following textures everything works, as well as when moving to another level, instead of waiting for a click from the player, the game works, although at the start of the 1st level waiting correctly.

have no other ideas.

local composer = require("composer")
local scene = composer.newScene()

local physics = require("physics")
physics.start()

local background = display.newRect(320, 240, 1000, 1000)
background:setFillColor(0.8, 0.8, 0.8, 1)

local ground = display.newRect(200, 300, 1000, 40)
ground:setFillColor(1, 1, 1, 1)
physics.addBody(ground, "static")

local startScreen = display.newGroup()

local startText = display.newText("Нажмите, чтобы начать!", 250, 150, "Helvetica", 25)
startText:setFillColor(0.2, 0.2, 0.2, 1)
startScreen:insert(startText)

local score = 0
local currentScore = display.newText(score, -70, 20, "Helvetica", 25)
local scoreText = display.newText("m / 200 m", 50, 20, "Helvetica", 25)

scoreText:setFillColor(0.4, 0.4, 0.4, 1)
currentScore:setFillColor(0.4, 0.4, 0.4, 1)

local startX = 50
local startY = 250

local player = display.newRect(startX, startY, 20, 60)
player:setFillColor(0.4, 0.4, 0.4, 0)
physics.addBody(player, "dynamic")
player.isJumping = false
player.isDucking = false
player.duckingCooldown = false
player.shootingCooldown = false
player.gravityScale = 0
player.isAlive = true

local sheetChar = 
{
    width = 300,
    height = 300,
    numFrames = 7
}

local imageSheet = graphics.newImageSheet("dino_sprite_sheet.png", sheetChar)
local sequenceData = 
{
    { name = "run", start = 1, count = 4, time = 600, loopCount = 0, loopDirection = "forward" },
    { name = "death", start = 5, count = 1, time = 1000, loopCount = 1 },
    { name = "duck", start = 6, count = 2, time = 600, loopCount = 0, loopDirection = "forward" },
    { name = "jump", start = 1, count = 1, time = 600, loopCount = 1 }
}

local character = display.newSprite(imageSheet, sequenceData)
character:scale(0.2, 0.2)

local function OnCollision(event)
    if event.phase == "began" and event.other == ground then
        player.isJumping = false
    end
end

local function Crash1(self, event)
    if (event.phase == "began" and (event.other.ID == "obstacle_t1" or 
    event.other.ID == "obstacle_t3" or event.other.ID == "obstacle_t4" or
    event.other.ID == "obstacle_t2" and not player.isDucking)) then
        print("+")
        player.isAlive = false
        transition.cancel()
        player:setLinearVelocity(0, 0)
    end
end

player.collision = Crash1

player:addEventListener("collision", player)
player:addEventListener("collision", OnCollision)

local function Crash2(self, event)
    if event.phase == "began" then
        if event.other.ID == "obstacle_t4" then
            if self.removeSelf then
                self:removeSelf()
            end
            if event.other and event.other.removeSelf then
                event.other:removeSelf()
            end
        elseif event.other.ID == "obstacle_t1" or event.other.ID == "obstacle_t2" or event.other.ID == "obstacle_t3" then
            if self.removeSelf then
                self:removeSelf()
            end
        end
    end
end

local function Jump(event)
    if player.isAlive then
        if event.phase == "began" and not player.isJumping and not player.isDucking then
            player.isJumping = true
            if character.sequence ~= "jump" then
                character:setSequence("jump")
                character:play("jump")
            end
            transition.to(player, {time=400, y=startY - 100, transition=easing.outQuad, onComplete=function()
                transition.to(player, {time=400, y=startY, transition=easing.inQuad})
            end})
            if character.sequence ~= "run" then
                character:setSequence("run")
                character:play("run")
            end
        end
    end
end

local function Duck(event)
    if player.isAlive then
        if event.phase == "began" and not player.isJumping and not player.isDucking 
        and not player.duckingCooldown then
            player.duckingCooldown = true
            player.isDucking = true
            if character.sequence ~= "duck" then
                character:setSequence("duck")
                character:play("duck")
            end
            timer.performWithDelay(1200, function()  
                player.duckingCooldown = false 
                player.isDucking = false
                if not player.isJumping and character.sequence ~= "run" then
                    character:setSequence("run")
                    character:play("run")
                end
            end)
        end
    end
end

local function Shoot(event)
    if event.phase == "began" and player.isAlive and not player.isJumping and not player.isDucking and not player.shootingCooldown then
        player.shootingCooldown = true
        local bullet = display.newCircle(player.x + 20, player.y, 5)
        bullet:setFillColor(1, 1, 1, 1)
        physics.addBody(bullet, "dynamic")
        bullet.gravityScale = 0
        bullet.isBullet = true
        bullet.ID = "bullet"
        bullet.isAlive = true
        bullet.collision = Crash2
        bullet:addEventListener( "collision", bullet )
        transition.to(bullet, {
            time = 500, 
            x = player.x + 100,
            onComplete = function()
                if bullet and bullet.removeSelf then
                    bullet:removeSelf()
                end
            end
        })
        timer.performWithDelay(2500, function() player.shootingCooldown = false end)
    end
end

local obstacleSpawnInterval = 3000
local obstacleSpeed = 4000

local sheetKakt = 
{
    width = 300,
    height = 300,
    numFrames = 5
}

local imageSheet2 = graphics.newImageSheet("kaktus_sprite_sheet.png", sheetKakt)
local sequenceData2 = 
{
    { name = "kakt1", start = 1, count = 1, time = 1000, loopCount = 1 },
    { name = "kakt2", start = 2, count = 1, time = 1000, loopCount = 1 },
    { name = "kakt3", start = 3, count = 1, time = 1000, loopCount = 1 },
    { name = "kakt4", start = 4, count = 2, time = 400, loopCount = 0, loopDirection = "forward" }
}

local function SpawnObstacle()
    if player.isAlive then
        local obstacleGroup = display.newGroup()
        local obstacle = display.newRect(0, 0, 40, 60)
        local charObstacle

        local obstacleType = math.random(1, 4)
        -- Птица
        if obstacleType == 1 then
            obstacle.height, obstacle.width = 20, 60
            obstacle.y = -25
            charObstacle = display.newSprite(imageSheet2, sequenceData2)
            charObstacle:setSequence("kakt4")
            charObstacle:scale(0.25, 0.25)
            obstacle.ID = "obstacle_t2"
        -- базовый кактус
        elseif obstacleType == 2 then
            obstacle.height, obstacle.width = 60, 40
            obstacle.y = 0
            charObstacle = display.newSprite(imageSheet2, sequenceData2)
            charObstacle:setSequence("kakt1")
            charObstacle:scale(0.25, 0.25)
            obstacle.ID = "obstacle_t1"
        -- Поле кактусов
        elseif obstacleType == 3 then
            obstacle.height, obstacle.width = 40, 75
            obstacle.y = 10
            charObstacle = display.newSprite(imageSheet2, sequenceData2)
            charObstacle:setSequence("kakt2")
            charObstacle:scale(0.35, 0.35)
            obstacle.ID = "obstacle_t3"
        -- Длинный кактус
        else
            obstacle.height, obstacle.width = 100, 40
            obstacle.y = -10
            charObstacle = display.newSprite(imageSheet2, sequenceData2)
            charObstacle:setSequence("kakt3")
            charObstacle:scale(0.5, 0.5)
            obstacle.ID = "obstacle_t4"
        end
        obstacle:setFillColor(0.3, 0.3, 0.3, 0.8)
        physics.addBody(obstacle, "dynamic")
        obstacle.gravityScale = 0
        obstacle.isSensor = true

        if charObstacle then
            charObstacle:play()
            obstacleGroup:insert(charObstacle)
        end

        obstacleGroup:insert(obstacle)

        obstacleGroup.x = 600
        obstacleGroup.y = 250

        transition.to(obstacleGroup, {time = obstacleSpeed, x = -150, onComplete = function()
            if obstacle and obstacle.removeSelf then
                obstacleGroup:removeSelf()
            end
        end})
    end
end

local jumpButton = display.newRect(-50, 300, 40, 30)
jumpButton:addEventListener("touch", Jump)
jumpButton:setFillColor(0, 0, 0, 0.01)

local duckButton = display.newRect(20, 300, 40, 30)
duckButton:addEventListener("touch", Duck)
duckButton:setFillColor(0, 0, 0, 0.01)

local shootButton = display.newRect(90, 300, 40, 30)
shootButton:addEventListener("touch", Shoot)
shootButton:setFillColor(0, 0, 0, 0.01)

local sheetChar3 = 
{
    width = 300,
    height = 300,
    numFrames = 3
}

local imageSheet3 = graphics.newImageSheet("button_sprite_sheet.png", sheetChar3)
local sequenceData3 = 
{
    { name = "b1", start = 1, count = 1, time = 1000, loopCount = 1 },
    { name = "b2", start = 2, count = 1, time = 1000, loopCount = 1 },
    { name = "b3", start = 3, count = 1, time = 1000, loopCount = 1 }
}

local p = 140
for i = 1, 3 do
    local charButton = display.newSprite(imageSheet3, sequenceData3)
    charButton:setSequence("b" .. i)
    charButton:scale(0.1, 0.1)
    charButton.x = -120 + i * p / 2
    charButton.y = 300
    charButton:play()
end

local function UpdateScore()
    if player.isAlive and score <= 200 then
        score = score + 1
        currentScore.text = score
    end
end

local function startGame(event)
    if event.phase == "ended" then
        display.remove(startScreen)
        UpdateScore()
        character:play("run")
        timer.performWithDelay(obstacleSpawnInterval, SpawnObstacle, 0)
        timer.performWithDelay(50, UpdateScore, 0)
    end
end

startScreen:addEventListener("touch", startGame)

local isEnd = false

local function Update()
    if not isEnd then
        if score == 200 then
            local textWin = display.newText("Вы победили!", 250, 150, "Helvetica", 25)
            textWin:setFillColor(0.2, 0.2, 0.2, 1)
            transition.cancel()
            timer.performWithDelay(2000, function()
                display.remove(textWin)
                composer.gotoScene("level2")
            end)
        end

        character.x, character.y = player.x, player.y
        if not player.isAlive then
            if character.sequence ~= "death" then
                character:setSequence("death")
                character:play("death")
                local textLose = display.newText("Вы проиграли!", 250, 150, "Helvetica", 25)
                textLose:setFillColor(0.2, 0.2, 0.2, 1)
                isEnd = true
                transition.cancel()
                timer.cancel(scoreTimer)
                timer.cancel(obstacleTimer)
                removeListeners()
            end
        elseif player.isDucking then
            if character.sequence ~= "duck" then
                character:setSequence("duck")
                character:play("duck")
            end
        elseif player.isJumping then
            if character.sequence ~= "jump" then
                character:setSequence("jump")
                character:play("jump")
            end
        elseif character.sequence ~= "run" then
            character:setSequence("run")
            character:play("run")
        end
    end
end

Runtime:addEventListener("enterFrame", Update)

return scene

Upvotes: 0

Views: 20

Answers (0)

Related Questions