One way Platform jumping using RectsOverlap

Started by Amon, April 04, 2019, 17:54:15

Previous topic - Next topic

Amon

I'm almost there but my logic is failing me. Can anybody help? you need a 64x64 image for the plats and similar for the player.

// Project: OneWayJump
// Created: 19-04-03

// show all errors
SetErrorMode(2)

// set window properties
SetWindowTitle("OneWayJump")
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(60, 0) // 30fps instead of 60 to save battery
SetScissor(0, 0, 0, 0) // use the maximum available screen space, no black borders
UseNewDefaultFonts(1)

img_GreyCube = LoadImage( "GreyCube.png" )
img_RedCube = LoadImage( "RedCube.png" )

type GTile
    id as integer
    x as integer
    y as integer
endtype
Global GList as GTile[]

global Level as integer
global levelD as string
global TileArray as integer[16,12]

global Player as integer
global PlayerX as float
global PlayerY as float

global JumpHeight as float = 15
global CanJump as Integer = 1
global IsJumping as integer = 0
global IsFalling as integer = 1
global Gravity as float = 0.8

Player = CreateSprite(img_RedCube)

Level = OpenToRead( "leveldata.txt" )
levelD = ReadLine(Level)
tempX as integer = 0
tempY as integer = 0
for x = 1 to len(levelD)
    if tempX > 15
        tempX = 0
        tempY = tempY + 1
    endif
    TileArray[ tempX,tempY ] = val(mid(levelD, x, 1) )
    if TileArray[ tempX,tempY ] = 1
        local gt as GTile
        gt.id = CreateSprite(img_GreyCube)
        SetSpriteOffset(gt.id,1,1)
        gt.x = tempX * 64
        gt.y = tempY * 64
        GList.insert(gt)
    endif
    if TileArray[ tempX,tempY ] = 2
        SetSpritePosition( Player, tempX * 64, tempY * 64 )
    endif
    tempX = tempX + 1
next
for x = GList.length to 0 step -1
    SetSpritePositionByOffset(GList[x].id, GList[x].x, GList[x].y)
next

PlayerX = GetSpriteX(Player)
PlayerY = GetSpriteY(Player)

do
    if GetRawKeyPressed(259) and CanJump = 1 // left control key
        CanJump = 0
        IsJumping = 1
    endif
   
    if IsJumping = 1
        PlayerY = PlayerY - JumpHeight
        JumpHeight = JumpHeight - Gravity
        if JumpHeight < 0
            IsFalling = 1
            IsJumping = 0
            JumpHeight = 15
        endif       
    endif
    if IsFalling = 1
        //CanJump = 0
        PlayerY = PlayerY + 6
        for x = GList.length to 0 step -1   
            if RectsOverlap(PlayerX, PlayerY, 64, 64, GList[x].x, GList[x].y, 64, 64) = 1
                if mod(PlayerY, 64) < JumpHeight * 2
                    PlayerY = PlayerY - mod(PlayerY, 64)
                    JumpHeight = 15
                    IsFalling = 0
                    CanJump = 1
                endif
                else
            endif
        next
    endif         

    if GetRawKeyState(37) = 1
        PlayerX = PlayerX - 4
    elseif GetRawKeyState(39) = 1
        PlayerX = PlayerX + 4
    endif
    SetSpritePosition(Player, PlayerX, PlayerY)
       
    Print(JumpHeight)
    Sync()
loop

function RectsOverlap(x1, y1, w1, h1, x2, y2, w2, h2)
    value = 1
    If x1 >= (x2 + w2) Or (x1 + w1) <= x2 Then value = 0
    If y1 >= (y2 + h2) Or (y1 + h1) <= y2 Then value = 0
endfunction value

Pakz

#1
https://cromdesi.home.xs4all.nl/agkmobile/

I was working on a tutorial book for agk mobile. In this book I put a platformer example using agk's build in physics for colliding with blocks. I put this in there for a base for further platformer work.

Maybe it might help?

Ps - it is at the bottom(last example)


EDIT : I got the code from this example here : ()


// ****************************************************************
// ****************************************************************
// Title : 2D Platform Template
// Version : 1.0
// Created : Paul Harthen (SpecTre)
// ****************************************************************
// ****************************************************************

// This code has been commented, however check the online documentation
// to assist your understanding.


// Set's the FPS of the game
SetSyncRate(60,0)


// ****************************************************************
// ****************************************************************
// SET UP CONSTANTS
// ****************************************************************
// ****************************************************************

// Constants are as they say constant! The settings can't be changing when
// the game is running.
// I set these to make it easier to read the code later down the line and also
// if you want a set value, eg, if you are detecting a key press, it is easier
// to ready in your code keyLeft than it is GetRawKeyState and a value all the time.
// You will see this in use later.

#constant keyLeft = GetRawKeyState(37)
#constant keyRight = GetRawKeyState(39)
#constant keySpace = GetRawKeyPressed(32)
#constant keyEsc = GetRawKeyState(27)
#constant true = 1
#constant false = 0
#constant windowWidth = 1280
#constant windowHeight = 800
#constant displayCentreX = 1280 * 0.5
#constant displayCentreY = 800 * 0.5
#constant blockSize = 64

// The blockSize is the size of a square tile on screen which makes up the level.

// ****************************************************************
// ****************************************************************
// SET UP ALL TYPE SETTINGS
// ****************************************************************
// ****************************************************************

// User defined types are a good way of storing data, I would advise to read
// the AGK documentation on these for further information but you should get an understanding
// of them when looking through the code.

Type mapDataType // Declares the name of the type

lvlX as integer // These are the fields of the type
lvlY as integer
lvlNum as integer
floorCollision as integer

EndType
global mapData as mapDataType // This creates a variable and declares it to the type in order to use it with, AS.
// I make the variable global so it can be used anywhere in the code, even within the functions.
// I then set the values of the fields below.
mapData.lvlX = 64 // Number of tiles wide for our level.
mapData.lvlY = 40 // Number of tiles high.
mapData.lvlNum = 1 // The level number, this can be changed in game for other levels.
mapData.floorCollision = 1 // A value to be checked to see if our character is touching the floor/platform.

// So here what we have done is create a type for the map information to use in creating the level.

// ****************************************************************
// ****************************************************************

// This is similar but this time it is a type for the player character.

Type playerType

savePointX as integer // X position to start the player from.
savePointY as integer // Y position
ID as integer // The sprite ID
rayDown as integer // This will be used to cast a ray down and test if the player is touching the floor
doubleJump as integer // For making the player double jump which is quite common in platform games now
xplayerMove# as float // Value for X movement
yplayerMove# as float // Value for Y movement
depth as integer // Player depth value which will be set to zero so it is always in front of other sprites

EndType
global player as playerType

player.rayDown = false
player.doubleJump = false
player.xplayerMove# = 300.0
player.yplayerMove# = 600.0
player.depth = 0


// ****************************************************************
// ****************************************************************
// SET UP THE MAIN SCREEN AND WORLD PHYSICS
// ****************************************************************
// ****************************************************************


// Let's set up the screen by giving the game window a title, setting a virtual
// resolution with a fixed width and height and put the window in the
// top left of the screen.

SetWindowTitle( "2D Platform Template" )
SetVirtualResolution( windowWidth, windowHeight )
SetWindowSize( windowWidth, windowHeight, 0 )
SetWindowPosition( 0, 0 )

// We are using the built in physics commands of AGK in this game.
// These 2 commands set up the scale and gravity for our game world
// just like in the real world.

//SetPhysicsDebugOn() // Try uncommenting this line to see what Physics Debug mode looks like

// Have a mess with these numbers to see how it affects the world.
SetPhysicsScale(0.05)
SetPhysicsGravity(0 , 1500)


// ****************************************************************
// ****************************************************************
// INITIATE FUNCTION CALLS
// ****************************************************************
// ****************************************************************

// Here we call the instructions in 2 functions one after the other.
// Once the program has completed all the instructions in the function,
// readLevel it will come back to here and then do the one for createPlayer
// before then continuing the program.
// If you look further down the code, these 2 functions are after the game loop.

readLevel()
createPlayer()


// ****************************************************************
// ****************************************************************
// SET UP PHYSICS FOR ALL SPRITES
// ****************************************************************
// ****************************************************************

// We now set physics settings for our game character which is a red block
// in this game. The sprite is player.ID which we created in the function
// createPlayer.

SetSpritePhysicsOn(player.ID,2) // Set the player sprite to have physics, 2 = dynamic so it can be affected by other objects
SetSpritePhysicsCanRotate (player.ID,0) // Turn off player sprite rotation so it can't be rotated! 1 is on.
SetSpritePhysicsFriction(player.ID,0) // Set the friction for the sprite, this is a float value between 0 and 1
SetSpritePhysicsRestitution(player.ID,0.1) // Sets the bounciness value of the sprite. A float value between 0 and 1
// Have a mess with these values and see what they do


// ****************************************************************
// ****************************************************************
// MAIN GAME LOOP
// ****************************************************************
// ****************************************************************

do // start of the main loop

// With this we cast a ray from the centre of the player sprite down to just below the bottom of the sprite
// This is used to see if the player has hit anything below it's feet, eg a platform so we know whether to jump of not when the
// space key is hit.
player.rayDown = PhysicsRayCastGroup(mapData.floorCollision, GetSpriteXByOffset(player.ID), GetSpriteYByOffset(player.ID), GetSpriteXByOffset(player.ID), GetSpriteYByOffset(player.ID) + (blockSize * 0.5 + 1))

    SetSpritePhysicsVelocity(player.ID, 0, GetSpritePhysicsVelocityY(player.ID)) // Gives the player a velocity, down in the Y direction
// The player will keep falling until it hits a floor sprite
   
if keyEsc // Quite the game after deleting all sprites
DeleteAllSprites()
DeleteAllImages()
End
endif

if keyLeft
SetSpritePhysicsVelocity(player.ID, - player.xPlayerMove#, GetSpritePhysicsVelocityY(player.ID)) // Move the player left, don't forget to play with these values set earlier to see what they do
endif

if keyRight
SetSpritePhysicsVelocity(player.ID, player.xPlayerMove#, GetSpritePhysicsVelocityY(player.ID)) // Move the player right
endif

if keySpace // Only jump if the player is on the ground or only once more after jumping off the ground
if player.rayDown = true
SetSpritePhysicsVelocity(player.ID, GetSpritePhysicsVelocityX(player.ID), - player.yPlayerMove#) // Move the player up in the Y direction, again play with the values set earlier
player.doubleJump = true
elseif player.rayDown = false and player.doubleJump = true
SetSpritePhysicsVelocity(player.ID, GetSpritePhysicsVelocityX(player.ID), - player.yPlayerMove#) // Again move the player up to jump
player.doubleJump = false
endif
endif


// This line is to control the camera to follow the player, try to comment this line out and see what it does
SetViewOffset(GetSpriteXByOffset(player.ID) - displayCentreX, GetSpriteYByOffset(player.ID) - displayCentreY*1.3)

Sync() // Update all the sprites on the screen

loop // end of the loop and this will go back to the start and repeat forever




// ****************************************************************
// ****************************************************************
// ALL GAME FUNCTIONS
// ****************************************************************
// ****************************************************************

// Functions are also a good thing to use in your code so again read about these in
// the documentation. Much better than the GOSUB command, as everyone will tell you on the forum!
// This is a basic Function example to get you started.

Function createPlayer()

// Here we create the player sprite, set it's size and colour of RED
// Set it's depth and position it on screen.
// The screen position was set with the map data and the character "&" in that data,
// this can be done using a map editor then and also things like coins, eggs and enemy
// positions can be set easily this way.
// If you look in the text level data you will see "&" somewhere

player.ID = CreateSprite(0)

SetSpriteSize(player.ID, blockSize * 0.5, blockSize)
SetSpriteColor(player.ID, 255, 0, 0, 255)
SetSpritePosition( player.ID, player.savePointX, player.savePointY )
SetSpriteOffset(player.ID, GetSpriteWidth(player.ID)/2, GetSpriteHeight(player.ID)/2)
SetSpriteDepth(player.ID, player.depth)

EndFunction

// ****************************************************************
// ****************************************************************

// This function reads the DATA in the text file and re-creates it on screen as a level to run around
Function readLevel()

file$ = "lvl_" + Str(mapData.lvlNum) + ".txt" // Creates a string variable and stores - "lvl_1.txt" in it
OpenToRead(1, file$) // Opens the text file to be read with the file$ variable above
// This file is stored in the media folder of our game

for y = 1 to mapData.lvlY // Y is 1 to 40, tiles hign on the screen
for x = 1 to mapData.lvlX // X is 1 to 64, tiles wide on the screen
// So it starts on Y/1 first and goes from X/1 to 64 then onto Y/2 and X/1 to 64 and so on to make the level

fileBlock$ = ReadLine(1) // Reads the first line of the text file, when it repeats it reads the next and so on

if fileBlock$ <> "0" and fileBlock$ <> "&" // Check to make sure we are not reading a value of 0 or & in the text file
// 0 is a blank so we don't want to create a tile there and & is the player start position
blockSprite=CreateSprite(0) // If not these then we create a tile sprite called blockSprite

if fileBlock$ = "1" // If the value in the text file is 1
// we make the tile green as 1 is a floor
SetSpriteColor(blockSprite, 50, 200, 50, 255)
SetSpritePhysicsOn(blockSprite,1) // Turn on physics for the floor sprite so that the player won't pass through it
SetSpriteGroup(blockSprite, mapData.floorCollision) // and create a group for it so we can test if the ray cast down from the player is touching
// the ground. We do this as we don't want our player to keep jumping when we hit the
// space bar constantly when it is not on the floor. We only want it to jump one more time
// in the air after we jump off the floor as this is then a double jump!
elseif fileBlock$ = "3" // If the value is a 3 then we set the tile to gray for the wall sprites
SetSpriteColor(blockSprite, 100, 100, 100, 255)
SetSpritePhysicsOn(blockSprite,1) // and again we turn the physics on so the player won't pass through the wall.
endif

SetSpriteSize(blockSprite, blockSize, blockSize) // For both wall and floor tiles we then set the size and position on screen.
SetSpritePosition( blockSprite, (x-1) * blockSize, (y-1) * blockSize )

elseif fileBlock$ = "&" // If the value is &, we don't create a tile sprite we just set the position for the player
// to start on screen
player.savePointX = (x-1) * blockSize
player.savePointY = (y-1) * blockSize
endif
next x
next y

CloseFile ( 1 ) // We use this command to close the text file when we have finished reading the DATA as we no longer need it now the level has been created
// and we don't want this to still be in memory when playing the game.

Endfunction

/*
Simplified level DATA explained

Key:
0 = Blank space
1 = Floor
3 = Wall
& = Player Start or Save point

3333333333333333333333333333
3000003333333000000333300003
3110000000000000000033000003
3001110000110000011133000003
3000000001331000003300001113
3000000000333000003300003333
3110000000000000000000003333
3000001111000111100000000003
300&000033000330000011000003
3333333333333333333333333333

If you look at this block, you will notice a game level, using the key above,
which contains platforms.
Our game has a bigger level than this with 64 x 40 blocks wide and high.
This is laid out row by row from top to bottom and each row is read from left to right.
You could put this DATA and read it here in the code, however we are reading
this DATA from a text file called - lvl_1.txt so you can see how to read from a text file
and also later once you understand, you can make DATA like this using a map editor yourself.
Open the .txt file in notepad and you will see similar information, however it
is in the form of one number per line so we read each line of the text file to
make the level.

Eg:
3
3
3
3
1
1
3
3

This way we can have multiple levels in their own text files which will save having a massive chunk
of code in your program.

Check this forum thread for further help to make a level editor and expand this example
when you understand this basic template.

https://forum.thegamecreators.com/thread/215384

This forum thread I created expands the game with layers in the map, ladders and collectables, for example,
like mushrooms and eggs. It also shows how to replace the blocks in this template with graphic tiles.

*/