Detecting only sprite collisions on top in agk

165 Views Asked by At

I am trying to make a blocks game like tipping blocks, where you stack the blocks on top of previous blocks to make a tower. The basic functions of the game work fine, however I am having some issues with the collision. Currently, I can get it to detect any collision but I want it only detect whether the block collides/lands on top of previous block and not the side. However it does not work as expected.

My method for checking whether collision is on top is using the if statement on line 128 checking whether GetSpriteY(count) + GetSpriteHeight(count)) <= GetSpriteY(count - 1), in theory this would check top left corner of falling sprite, add the sprite's height and see if it less than the previous sprite's y coordinate (meaning current sprite collides on top of previous sprite). However, it does not work and the sprites just keep falling through each other. It works when I switch the "<" to a ">" but detects all collisions and does not only detect collisions on top.

Not sure what to do...Any help is appreciated

// Project: tippin
// Created: 2021-06-08

// show all errors
SetErrorMode(2)

// set window properties
SetWindowTitle( "tippin" )
SetWindowSize( 1024, 768, 0 )
SetWindowAllowResize( 1 ) // allow the user to resize the window

// set display properties
SetVirtualResolution( 1024, 768 ) // doesn't have to match the window
SetOrientationAllowed( 1, 1, 1, 1 ) // allow both portrait and landscape on mobile devices
SetSyncRate( 30, 0 ) // 30fps instead of 60 to save battery
SetScissor( 0,0,0,0 ) // use the maximum available screen space, no black borders
UseNewDefaultFonts( 1 ) // since version 2.0.22 we can use nicer default fonts




block2x= 450
block2y = 10
//LoadImage(2,"ball.png")



base =1
//make base block
//LoadImage(base,"hoop.png")
CreateSprite(base,0)
SetSpriteSize(base,170,50)
SetSpritePosition(base,400,700)
SetSpriteColor(base,55,232,35,255)




//define variables
startScreen=1
dx1=1
cx1=0.6
dy1=1
x1=1
cy1=0
 
score= 0
gameon= 1
count=2      
needNewSprite= 1

do
   while startScreen=1
        Print("Tippin Blocks")
        Print("Press ENTER to begin")
        Print("Press ESC to quit")
        if GetRawKeyPressed(13)=1 //enter to begin
            startScreen=0
            exit
        else
            if GetRawKeyPressed(27)=1 //end game if esc is pressed
                end
            endif
        endif
        sync()
    //box can move
    SetSpritePhysicsOn(1,2)
    
    
    endwhile
    

i = 0   
Print(score)
    while i < 10 and gameon
        i = i + 1
        //i allows loop to not keep running forever
     
        //to make new sprites
        if needNewSprite
            CreateSprite(count,0)
            SetSpriteSize(count,100,100)
            SetSpritePosition(count,400,block2y)
            SetSpriteColor(count,200,200,220,200)
            SetSpritePhysicsOn(count,3)
            needNewSprite = 0
        endif
     
        //to make the base bounce off walls   
        basex = GetSpriteX(1)
     
        if basex <= 0 //if hits left side then change speed and direction to the right
            dx1 = 1
            basex = 0
            //SetSpritePhysicsVelocity(2,100,0)
        endif
         
        if  basex >= GetVirtualWidth() - GetSpriteWidth(base) //if hits right side then change speed to left side
            dx1 = -1
            basex = GetVirtualWidth() - GetSpriteWidth(base)
            //SetSpritePhysicsVelocity(2,-100,0)
        endif
     
        basex = basex + dx1*cx1
        //makes the base move
        SetSpritePosition(base, basex,GetVirtualHeight() - GetSpriteHeight(base))
     
     
        //if press space button,move the ball down
        if GetRawKeyPressed(32)
            SetSpritePhysicsVelocity(count,0,800)
    
        endif
    
    //check if sprite collides with previous sprite
        if GetSpriteCollision(count,count-1)=1
            //check if it collision is on the top surface
            //not working properly right now, counts every collision
            if count = 2:
                blockx = GetSpriteX(count) + dx1*cx1
                SetSpritePosition(count,blockx,GetSpriteY(count))
                score = score + 1
                count = count + 1
                needNewSprite = 1
                continue
            endif
            
            if (GetSpriteY(count) + GetSpriteHeight(count)) <= GetSpriteY(count - 1)
                blockx = GetSpriteX(count) + dx1*cx1
                SetSpritePosition(count,blockx,GetSpriteY(count))
                score = score + 1
                //get x coordinate of collision and make it go in same direction as base block
                //need new sprite
                count = count + 1
                needNewSprite = 1
                continue //prevents errors since next sprite has not been made
            endif
            
        endif
     
     
        //end if hits bottom
        if GetSpriteY(count) >= GetVirtualHeight() - GetSpriteHeight(count)
            end
            gameon = 0
      
        endif  
        //for loop where to start and till when
        //from the second block to the second last block itll keep updating the location of each
        for block = 2 to count - 1:
            blockx = GetSpriteX(block) + dx1*cx1
            SetSpritePosition(block,blockx,GetSpriteY(block))
        next block
     
    endwhile
    
    
    
    
     
    Sync()
loop







 








1

There are 1 best solutions below

0
Phaelax z On

From AGK's manual:

Once you have set a sprite to be controlled by physics you should use SetSpritePosition and SetSpriteAngle sparingly as these will interrupt the physics motion of the sprite.

Either use the internal physics system or control everything yourself, it's not a good idea to mix the two as it appears you're trying to do. My guess is there's an issue with how/when you're incrementing "count", and that it's not checking the sprites you might think it should be checking.

Here's a simple framework that might help you out. I don't have AGK in front of me at the moment so I'm unable to test. My other tip for you would be to choose more meaningful variable names.

One last thing, as a nearly 20 year member of the AGK forum myself, it really is the best place to seek help for questions regarding this language as most other places are generally unfamiliar with it.

// To track the sprites/blocks on the stack
Global stackedBlocks as integer[]


baseSprite = newBlock()


topSprite = baseSprite




DO


    // Loop through all sprites in the stack.
    // Due to movement of the base platform, blocks could fall off 
    // and thus changing the top most block in the stack. This loop
    // not only determines which block is currently on top but also
    // checks for blocks that may have fallen off the map
    
    y = 9999
    
    for i = 0 to stackedBlocks.length-1
        if stackedBlocks[i] <> fallingSprite
            if getSpriteY(stackedBlocks[i]) < y
                topSprite = stackedBlocks[i]
            endif
        endif
        
        // Block fell off the map
        if getSpriteY(stackedBlocks[i]) > getVirtualHeight()
            // do something here
        endif
        
    next i
    
    


    // If the falling block hits the top of the stack
    if getPhysicsCollision(fallingSprite, topSprite) = 1
        
        // The sprite that was falling should now be on the top of the stack
        topSprite = fallingSprite
        
        // This block is now on the stack, add the sprite index to the array
        stackedBlocks.insert(topSprite)
        
        fallingSprite = newBlock()

    endif
    
    

    


    sync()
LOOP





// Create a new block ready for dropping
function newBlock()
    s = createSprite(0)
    setSpriteSize(s, 170, 50)
    setSpritePosition(s, 400, 700)
    setSpriteColor(s, 55, 232, 35, 255)
    
    stackedBlocks.insert(s)
    
endfunction s